diff options
Diffstat (limited to 'libziparchive/include/ziparchive/zip_writer.h')
-rw-r--r-- | libziparchive/include/ziparchive/zip_writer.h | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/libziparchive/include/ziparchive/zip_writer.h b/libziparchive/include/ziparchive/zip_writer.h new file mode 100644 index 000000000..c350a2750 --- /dev/null +++ b/libziparchive/include/ziparchive/zip_writer.h | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 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 | */ | ||
16 | |||
17 | #ifndef LIBZIPARCHIVE_ZIPWRITER_H_ | ||
18 | #define LIBZIPARCHIVE_ZIPWRITER_H_ | ||
19 | |||
20 | #include <cstdio> | ||
21 | #include <ctime> | ||
22 | |||
23 | #include <memory> | ||
24 | #include <string> | ||
25 | #include <vector> | ||
26 | |||
27 | #include "android-base/macros.h" | ||
28 | #include "utils/Compat.h" | ||
29 | |||
30 | struct z_stream_s; | ||
31 | typedef struct z_stream_s z_stream; | ||
32 | |||
33 | /** | ||
34 | * Writes a Zip file via a stateful interface. | ||
35 | * | ||
36 | * Example: | ||
37 | * | ||
38 | * FILE* file = fopen("path/to/zip.zip", "wb"); | ||
39 | * | ||
40 | * ZipWriter writer(file); | ||
41 | * | ||
42 | * writer.StartEntry("test.txt", ZipWriter::kCompress | ZipWriter::kAlign); | ||
43 | * writer.WriteBytes(buffer, bufferLen); | ||
44 | * writer.WriteBytes(buffer2, bufferLen2); | ||
45 | * writer.FinishEntry(); | ||
46 | * | ||
47 | * writer.StartEntry("empty.txt", 0); | ||
48 | * writer.FinishEntry(); | ||
49 | * | ||
50 | * writer.Finish(); | ||
51 | * | ||
52 | * fclose(file); | ||
53 | */ | ||
54 | class ZipWriter { | ||
55 | public: | ||
56 | enum { | ||
57 | /** | ||
58 | * Flag to compress the zip entry using deflate. | ||
59 | */ | ||
60 | kCompress = 0x01, | ||
61 | |||
62 | /** | ||
63 | * Flag to align the zip entry data on a 32bit boundary. Useful for | ||
64 | * mmapping the data at runtime. | ||
65 | */ | ||
66 | kAlign32 = 0x02, | ||
67 | }; | ||
68 | |||
69 | /** | ||
70 | * A struct representing a zip file entry. | ||
71 | */ | ||
72 | struct FileEntry { | ||
73 | std::string path; | ||
74 | uint16_t compression_method; | ||
75 | uint32_t crc32; | ||
76 | uint32_t compressed_size; | ||
77 | uint32_t uncompressed_size; | ||
78 | uint16_t last_mod_time; | ||
79 | uint16_t last_mod_date; | ||
80 | uint32_t padding_length; | ||
81 | off64_t local_file_header_offset; | ||
82 | }; | ||
83 | |||
84 | static const char* ErrorCodeString(int32_t error_code); | ||
85 | |||
86 | /** | ||
87 | * Create a ZipWriter that will write into a FILE stream. The file should be opened with | ||
88 | * open mode of "wb" or "w+b". ZipWriter does not take ownership of the file stream. The | ||
89 | * caller is responsible for closing the file. | ||
90 | */ | ||
91 | explicit ZipWriter(FILE* f); | ||
92 | |||
93 | // Move constructor. | ||
94 | ZipWriter(ZipWriter&& zipWriter); | ||
95 | |||
96 | // Move assignment. | ||
97 | ZipWriter& operator=(ZipWriter&& zipWriter); | ||
98 | |||
99 | /** | ||
100 | * Starts a new zip entry with the given path and flags. | ||
101 | * Flags can be a bitwise OR of ZipWriter::kCompress and ZipWriter::kAlign. | ||
102 | * Subsequent calls to WriteBytes(const void*, size_t) will add data to this entry. | ||
103 | * Returns 0 on success, and an error value < 0 on failure. | ||
104 | */ | ||
105 | int32_t StartEntry(const char* path, size_t flags); | ||
106 | |||
107 | /** | ||
108 | * Starts a new zip entry with the given path and flags, where the | ||
109 | * entry will be aligned to the given alignment. | ||
110 | * Flags can only be ZipWriter::kCompress. Using the flag ZipWriter::kAlign32 | ||
111 | * will result in an error. | ||
112 | * Subsequent calls to WriteBytes(const void*, size_t) will add data to this entry. | ||
113 | * Returns 0 on success, and an error value < 0 on failure. | ||
114 | */ | ||
115 | int32_t StartAlignedEntry(const char* path, size_t flags, uint32_t alignment); | ||
116 | |||
117 | /** | ||
118 | * Same as StartEntry(const char*, size_t), but sets a last modified time for the entry. | ||
119 | */ | ||
120 | int32_t StartEntryWithTime(const char* path, size_t flags, time_t time); | ||
121 | |||
122 | /** | ||
123 | * Same as StartAlignedEntry(const char*, size_t), but sets a last modified time for the entry. | ||
124 | */ | ||
125 | int32_t StartAlignedEntryWithTime(const char* path, size_t flags, time_t time, uint32_t alignment); | ||
126 | |||
127 | /** | ||
128 | * Writes bytes to the zip file for the previously started zip entry. | ||
129 | * Returns 0 on success, and an error value < 0 on failure. | ||
130 | */ | ||
131 | int32_t WriteBytes(const void* data, size_t len); | ||
132 | |||
133 | /** | ||
134 | * Finish a zip entry started with StartEntry(const char*, size_t) or | ||
135 | * StartEntryWithTime(const char*, size_t, time_t). This must be called before | ||
136 | * any new zip entries are started, or before Finish() is called. | ||
137 | * Returns 0 on success, and an error value < 0 on failure. | ||
138 | */ | ||
139 | int32_t FinishEntry(); | ||
140 | |||
141 | /** | ||
142 | * Discards the last-written entry. Can only be called after an entry has been written using | ||
143 | * FinishEntry(). | ||
144 | * Returns 0 on success, and an error value < 0 on failure. | ||
145 | */ | ||
146 | int32_t DiscardLastEntry(); | ||
147 | |||
148 | /** | ||
149 | * Sets `out_entry` to the last entry written after a call to FinishEntry(). | ||
150 | * Returns 0 on success, and an error value < 0 if no entries have been written. | ||
151 | */ | ||
152 | int32_t GetLastEntry(FileEntry* out_entry); | ||
153 | |||
154 | /** | ||
155 | * Writes the Central Directory Headers and flushes the zip file stream. | ||
156 | * Returns 0 on success, and an error value < 0 on failure. | ||
157 | */ | ||
158 | int32_t Finish(); | ||
159 | |||
160 | private: | ||
161 | DISALLOW_COPY_AND_ASSIGN(ZipWriter); | ||
162 | |||
163 | int32_t HandleError(int32_t error_code); | ||
164 | int32_t PrepareDeflate(); | ||
165 | int32_t StoreBytes(FileEntry* file, const void* data, size_t len); | ||
166 | int32_t CompressBytes(FileEntry* file, const void* data, size_t len); | ||
167 | int32_t FlushCompressedBytes(FileEntry* file); | ||
168 | |||
169 | enum class State { | ||
170 | kWritingZip, | ||
171 | kWritingEntry, | ||
172 | kDone, | ||
173 | kError, | ||
174 | }; | ||
175 | |||
176 | FILE* file_; | ||
177 | bool seekable_; | ||
178 | off64_t current_offset_; | ||
179 | State state_; | ||
180 | std::vector<FileEntry> files_; | ||
181 | FileEntry current_file_entry_; | ||
182 | |||
183 | std::unique_ptr<z_stream, void (*)(z_stream*)> z_stream_; | ||
184 | std::vector<uint8_t> buffer_; | ||
185 | }; | ||
186 | |||
187 | #endif /* LIBZIPARCHIVE_ZIPWRITER_H_ */ | ||