blob: 9ee4abec2901350b3b5c9d02381219d6e0ad2170 [file] [log] [blame]
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -07001/*
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 "base/macros.h"
21#include <utils/Compat.h>
22
23#include <cstdio>
24#include <string>
25#include <ctime>
26#include <vector>
27
28/**
29 * Writes a Zip file via a stateful interface.
30 *
31 * Example:
32 *
33 * FILE* file = fopen("path/to/zip.zip", "wb");
34 *
35 * ZipWriter writer(file);
36 *
37 * writer.StartEntry("test.txt", ZipWriter::kCompress | ZipWriter::kAlign);
38 * writer.WriteBytes(buffer, bufferLen);
39 * writer.WriteBytes(buffer2, bufferLen2);
40 * writer.FinishEntry();
41 *
42 * writer.StartEntry("empty.txt", 0);
43 * writer.FinishEntry();
44 *
45 * writer.Finish();
46 *
47 * fclose(file);
48 */
49class ZipWriter {
50public:
51 enum {
52 /**
53 * Flag to compress the zip entry using deflate.
54 */
55 kCompress = 0x01,
56
57 /**
58 * Flag to align the zip entry data on a 32bit boundary. Useful for
59 * mmapping the data at runtime.
60 */
61 kAlign32 = 0x02,
62 };
63
64 static const char* ErrorCodeString(int32_t error_code);
65
66 /**
67 * Create a ZipWriter that will write into a FILE stream. The file should be opened with
68 * open mode of "wb" or "w+b". ZipWriter does not take ownership of the file stream. The
69 * caller is responsible for closing the file.
70 */
71 explicit ZipWriter(FILE* f);
72
73 // Move constructor.
74 ZipWriter(ZipWriter&& zipWriter);
75
76 // Move assignment.
77 ZipWriter& operator=(ZipWriter&& zipWriter);
78
79 /**
80 * Starts a new zip entry with the given path and flags.
81 * Flags can be a bitwise OR of ZipWriter::kCompress and ZipWriter::kAlign.
82 * Subsequent calls to WriteBytes(const void*, size_t) will add data to this entry.
83 * Returns 0 on success, and an error value < 0 on failure.
84 */
85 int32_t StartEntry(const char* path, size_t flags);
86
87 /**
88 * Same as StartEntry(const char*, size_t), but sets a last modified time for the entry.
89 */
90 int32_t StartEntryWithTime(const char* path, size_t flags, time_t time);
91
92 /**
93 * Writes bytes to the zip file for the previously started zip entry.
94 * Returns 0 on success, and an error value < 0 on failure.
95 */
96 int32_t WriteBytes(const void* data, size_t len);
97
98 /**
99 * Finish a zip entry started with StartEntry(const char*, size_t) or
100 * StartEntryWithTime(const char*, size_t, time_t). This must be called before
101 * any new zip entries are started, or before Finish() is called.
102 * Returns 0 on success, and an error value < 0 on failure.
103 */
104 int32_t FinishEntry();
105
106 /**
107 * Writes the Central Directory Headers and flushes the zip file stream.
108 * Returns 0 on success, and an error value < 0 on failure.
109 */
110 int32_t Finish();
111
112private:
113 DISALLOW_COPY_AND_ASSIGN(ZipWriter);
114
115 int32_t HandleError(int32_t error_code);
116
117 struct FileInfo {
118 std::string path;
119 uint16_t compression_method;
120 uint32_t crc32;
121 uint32_t compressed_size;
122 uint32_t uncompressed_size;
123 uint16_t last_mod_time;
124 uint16_t last_mod_date;
125 uint32_t local_file_header_offset;
126 };
127
128 enum class State {
129 kWritingZip,
130 kWritingEntry,
131 kDone,
132 kError,
133 };
134
135 FILE* file_;
136 off64_t current_offset_;
137 State state_;
138 std::vector<FileInfo> files_;
139};
140
141#endif /* LIBZIPARCHIVE_ZIPWRITER_H_ */