blob: 9a3cdb434bb2ced8e95a4cd9a9d7a61667bf99a5 [file] [log] [blame]
Narayan Kamath7462f022013-11-21 13:05:04 +00001/*
2 * Copyright (C) 2013 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#include "ziparchive/zip_archive.h"
18
Narayan Kamath00a258c2013-12-13 16:06:19 +000019#include <errno.h>
Dmitriy Ivanov40b52b22014-07-15 19:33:00 -070020#include <fcntl.h>
Narayan Kamath00a258c2013-12-13 16:06:19 +000021#include <getopt.h>
Narayan Kamath7462f022013-11-21 13:05:04 +000022#include <stdio.h>
Narayan Kamath00a258c2013-12-13 16:06:19 +000023#include <unistd.h>
24#include <vector>
25
Narayan Kamathf899bd52015-04-17 11:53:14 +010026#include <base/file.h>
Narayan Kamath7462f022013-11-21 13:05:04 +000027#include <gtest/gtest.h>
28
Narayan Kamath58aaf462013-12-10 16:47:14 +000029static std::string test_data_dir;
Narayan Kamath7462f022013-11-21 13:05:04 +000030
Neil Fullerb1a113f2014-07-25 14:43:04 +010031static const std::string kMissingZip = "missing.zip";
Narayan Kamath58aaf462013-12-10 16:47:14 +000032static const std::string kValidZip = "valid.zip";
33
34static const uint8_t kATxtContents[] = {
35 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
36 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
37 '\n'
38};
39
40static const uint8_t kBTxtContents[] = {
41 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
42 '\n'
43};
44
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +010045static const uint16_t kATxtNameLength = 5;
46static const uint16_t kBTxtNameLength = 5;
47static const uint16_t kNonexistentTxtNameLength = 15;
48static const uint16_t kEmptyTxtNameLength = 9;
49
50static const uint8_t kATxtName[kATxtNameLength] = {
51 'a', '.', 't', 'x', 't'
52};
53
54static const uint8_t kBTxtName[kBTxtNameLength] = {
55 'b', '.', 't', 'x', 't'
56};
57
58static const uint8_t kNonexistentTxtName[kNonexistentTxtNameLength] = {
59 'n', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', '.', 't', 'x' ,'t'
60};
61
62static const uint8_t kEmptyTxtName[kEmptyTxtNameLength] = {
63 'e', 'm', 'p', 't', 'y', '.', 't', 'x', 't'
64};
65
Narayan Kamath58aaf462013-12-10 16:47:14 +000066static int32_t OpenArchiveWrapper(const std::string& name,
67 ZipArchiveHandle* handle) {
68 const std::string abs_path = test_data_dir + "/" + name;
69 return OpenArchive(abs_path.c_str(), handle);
70}
71
72static void AssertNameEquals(const std::string& name_str,
Yusuke Sato07447542015-06-25 14:39:19 -070073 const ZipString& name) {
Narayan Kamath58aaf462013-12-10 16:47:14 +000074 ASSERT_EQ(name_str.size(), name.name_length);
75 ASSERT_EQ(0, memcmp(name_str.c_str(), name.name, name.name_length));
76}
77
78TEST(ziparchive, Open) {
79 ZipArchiveHandle handle;
80 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
81
82 CloseArchive(handle);
83}
84
Neil Fullerb1a113f2014-07-25 14:43:04 +010085TEST(ziparchive, OpenMissing) {
86 ZipArchiveHandle handle;
87 ASSERT_NE(0, OpenArchiveWrapper(kMissingZip, &handle));
88
89 // Confirm the file descriptor is not going to be mistaken for a valid one.
90 ASSERT_EQ(-1, GetFileDescriptor(handle));
91}
92
Dmitriy Ivanov40b52b22014-07-15 19:33:00 -070093TEST(ziparchive, OpenAssumeFdOwnership) {
94 int fd = open((test_data_dir + "/" + kValidZip).c_str(), O_RDONLY);
95 ASSERT_NE(-1, fd);
96 ZipArchiveHandle handle;
97 ASSERT_EQ(0, OpenArchiveFd(fd, "OpenWithAssumeFdOwnership", &handle));
98 CloseArchive(handle);
99 ASSERT_EQ(-1, lseek(fd, 0, SEEK_SET));
100 ASSERT_EQ(EBADF, errno);
101}
102
103TEST(ziparchive, OpenDoNotAssumeFdOwnership) {
104 int fd = open((test_data_dir + "/" + kValidZip).c_str(), O_RDONLY);
105 ASSERT_NE(-1, fd);
106 ZipArchiveHandle handle;
107 ASSERT_EQ(0, OpenArchiveFd(fd, "OpenWithAssumeFdOwnership", &handle, false));
108 CloseArchive(handle);
109 ASSERT_EQ(0, lseek(fd, 0, SEEK_SET));
110 close(fd);
111}
112
Narayan Kamath58aaf462013-12-10 16:47:14 +0000113TEST(ziparchive, Iteration) {
114 ZipArchiveHandle handle;
115 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
116
117 void* iteration_cookie;
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700118 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, NULL, NULL));
Narayan Kamath7462f022013-11-21 13:05:04 +0000119
120 ZipEntry data;
Yusuke Sato07447542015-06-25 14:39:19 -0700121 ZipString name;
Narayan Kamath58aaf462013-12-10 16:47:14 +0000122
123 // b/c.txt
124 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
125 AssertNameEquals("b/c.txt", name);
126
127 // b/d.txt
128 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
129 AssertNameEquals("b/d.txt", name);
130
131 // a.txt
132 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
133 AssertNameEquals("a.txt", name);
134
135 // b.txt
136 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
137 AssertNameEquals("b.txt", name);
138
139 // b/
140 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
141 AssertNameEquals("b/", name);
142
143 // End of iteration.
144 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
145
146 CloseArchive(handle);
147}
148
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700149TEST(ziparchive, IterationWithPrefix) {
150 ZipArchiveHandle handle;
151 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
152
153 void* iteration_cookie;
Yusuke Sato07447542015-06-25 14:39:19 -0700154 ZipString prefix("b/");
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700155 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, &prefix, NULL));
156
157 ZipEntry data;
Yusuke Sato07447542015-06-25 14:39:19 -0700158 ZipString name;
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700159
160 // b/c.txt
161 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
162 AssertNameEquals("b/c.txt", name);
163
164 // b/d.txt
165 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
166 AssertNameEquals("b/d.txt", name);
167
168 // b/
169 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
170 AssertNameEquals("b/", name);
171
172 // End of iteration.
173 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
174
175 CloseArchive(handle);
176}
177
178TEST(ziparchive, IterationWithSuffix) {
179 ZipArchiveHandle handle;
180 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
181
182 void* iteration_cookie;
Yusuke Sato07447542015-06-25 14:39:19 -0700183 ZipString suffix(".txt");
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700184 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, NULL, &suffix));
185
186 ZipEntry data;
Yusuke Sato07447542015-06-25 14:39:19 -0700187 ZipString name;
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700188
189 // b/c.txt
190 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
191 AssertNameEquals("b/c.txt", name);
192
193 // b/d.txt
194 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
195 AssertNameEquals("b/d.txt", name);
196
197 // a.txt
198 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
199 AssertNameEquals("a.txt", name);
200
201 // b.txt
202 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
203 AssertNameEquals("b.txt", name);
204
205 // End of iteration.
206 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
207
208 CloseArchive(handle);
209}
210
211TEST(ziparchive, IterationWithPrefixAndSuffix) {
212 ZipArchiveHandle handle;
213 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
214
215 void* iteration_cookie;
Yusuke Sato07447542015-06-25 14:39:19 -0700216 ZipString prefix("b");
217 ZipString suffix(".txt");
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700218 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, &prefix, &suffix));
219
220 ZipEntry data;
Yusuke Sato07447542015-06-25 14:39:19 -0700221 ZipString name;
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700222
223 // b/c.txt
224 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
225 AssertNameEquals("b/c.txt", name);
226
227 // b/d.txt
228 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
229 AssertNameEquals("b/d.txt", name);
230
231 // b.txt
232 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
233 AssertNameEquals("b.txt", name);
234
235 // End of iteration.
236 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
237
238 CloseArchive(handle);
239}
240
241TEST(ziparchive, IterationWithBadPrefixAndSuffix) {
242 ZipArchiveHandle handle;
243 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
244
245 void* iteration_cookie;
Yusuke Sato07447542015-06-25 14:39:19 -0700246 ZipString prefix("x");
247 ZipString suffix("y");
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700248 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, &prefix, &suffix));
249
250 ZipEntry data;
Yusuke Sato07447542015-06-25 14:39:19 -0700251 ZipString name;
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700252
253 // End of iteration.
254 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
255
256 CloseArchive(handle);
257}
258
Narayan Kamath58aaf462013-12-10 16:47:14 +0000259TEST(ziparchive, FindEntry) {
260 ZipArchiveHandle handle;
261 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
262
263 ZipEntry data;
Yusuke Sato07447542015-06-25 14:39:19 -0700264 ZipString name;
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100265 name.name = kATxtName;
266 name.name_length = kATxtNameLength;
267 ASSERT_EQ(0, FindEntry(handle, name, &data));
Narayan Kamath58aaf462013-12-10 16:47:14 +0000268
269 // Known facts about a.txt, from zipinfo -v.
270 ASSERT_EQ(63, data.offset);
271 ASSERT_EQ(kCompressDeflated, data.method);
272 ASSERT_EQ(static_cast<uint32_t>(17), data.uncompressed_length);
273 ASSERT_EQ(static_cast<uint32_t>(13), data.compressed_length);
274 ASSERT_EQ(0x950821c5, data.crc32);
275
276 // An entry that doesn't exist. Should be a negative return code.
Yusuke Sato07447542015-06-25 14:39:19 -0700277 ZipString absent_name;
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100278 absent_name.name = kNonexistentTxtName;
279 absent_name.name_length = kNonexistentTxtNameLength;
280 ASSERT_LT(FindEntry(handle, absent_name, &data), 0);
Narayan Kamath58aaf462013-12-10 16:47:14 +0000281
282 CloseArchive(handle);
283}
284
Mykola Kondratenko50afc152014-09-08 12:46:37 +0200285TEST(ziparchive, TestInvalidDeclaredLength) {
286 ZipArchiveHandle handle;
287 ASSERT_EQ(0, OpenArchiveWrapper("declaredlength.zip", &handle));
288
289 void* iteration_cookie;
Yusuke Sato07447542015-06-25 14:39:19 -0700290 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, NULL, NULL));
Mykola Kondratenko50afc152014-09-08 12:46:37 +0200291
Yusuke Sato07447542015-06-25 14:39:19 -0700292 ZipString name;
Mykola Kondratenko50afc152014-09-08 12:46:37 +0200293 ZipEntry data;
294
295 ASSERT_EQ(Next(iteration_cookie, &data, &name), 0);
296 ASSERT_EQ(Next(iteration_cookie, &data, &name), 0);
297
298 CloseArchive(handle);
299}
300
Narayan Kamath58aaf462013-12-10 16:47:14 +0000301TEST(ziparchive, ExtractToMemory) {
302 ZipArchiveHandle handle;
303 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
304
305 // An entry that's deflated.
306 ZipEntry data;
Yusuke Sato07447542015-06-25 14:39:19 -0700307 ZipString a_name;
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100308 a_name.name = kATxtName;
309 a_name.name_length = kATxtNameLength;
310 ASSERT_EQ(0, FindEntry(handle, a_name, &data));
Narayan Kamath58aaf462013-12-10 16:47:14 +0000311 const uint32_t a_size = data.uncompressed_length;
312 ASSERT_EQ(a_size, sizeof(kATxtContents));
313 uint8_t* buffer = new uint8_t[a_size];
314 ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer, a_size));
315 ASSERT_EQ(0, memcmp(buffer, kATxtContents, a_size));
316 delete[] buffer;
317
318 // An entry that's stored.
Yusuke Sato07447542015-06-25 14:39:19 -0700319 ZipString b_name;
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100320 b_name.name = kBTxtName;
321 b_name.name_length = kBTxtNameLength;
322 ASSERT_EQ(0, FindEntry(handle, b_name, &data));
Narayan Kamath58aaf462013-12-10 16:47:14 +0000323 const uint32_t b_size = data.uncompressed_length;
324 ASSERT_EQ(b_size, sizeof(kBTxtContents));
325 buffer = new uint8_t[b_size];
326 ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer, b_size));
327 ASSERT_EQ(0, memcmp(buffer, kBTxtContents, b_size));
328 delete[] buffer;
329
330 CloseArchive(handle);
331}
332
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100333static const uint32_t kEmptyEntriesZip[] = {
Narayan Kamath48953a12014-01-24 12:32:39 +0000334 0x04034b50, 0x0000000a, 0x63600000, 0x00004438, 0x00000000, 0x00000000,
335 0x00090000, 0x6d65001c, 0x2e797470, 0x55747874, 0x03000954, 0x52e25c13,
336 0x52e25c24, 0x000b7875, 0x42890401, 0x88040000, 0x50000013, 0x1e02014b,
337 0x00000a03, 0x60000000, 0x00443863, 0x00000000, 0x00000000, 0x09000000,
338 0x00001800, 0x00000000, 0xa0000000, 0x00000081, 0x706d6500, 0x742e7974,
339 0x54557478, 0x13030005, 0x7552e25c, 0x01000b78, 0x00428904, 0x13880400,
340 0x4b500000, 0x00000605, 0x00010000, 0x004f0001, 0x00430000, 0x00000000 };
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100341
Narayan Kamathf899bd52015-04-17 11:53:14 +0100342// This is a zip file containing a single entry (ab.txt) that contains
343// 90072 repetitions of the string "ab\n" and has an uncompressed length
344// of 270216 bytes.
345static const uint16_t kAbZip[] = {
346 0x4b50, 0x0403, 0x0014, 0x0000, 0x0008, 0x51d2, 0x4698, 0xc4b0,
347 0x2cda, 0x011b, 0x0000, 0x1f88, 0x0004, 0x0006, 0x001c, 0x6261,
348 0x742e, 0x7478, 0x5455, 0x0009, 0x7c03, 0x3a09, 0x7c55, 0x3a09,
349 0x7555, 0x0b78, 0x0100, 0x8904, 0x0042, 0x0400, 0x1388, 0x0000,
350 0xc2ed, 0x0d31, 0x0000, 0x030c, 0x7fa0, 0x3b2e, 0x22ff, 0xa2aa,
351 0x841f, 0x45fc, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
352 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
353 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
354 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
355 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
356 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
357 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
358 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
359 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
360 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
361 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
362 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
363 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
364 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
365 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
366 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
367 0x5555, 0x5555, 0x5555, 0x5555, 0xdd55, 0x502c, 0x014b, 0x1e02,
368 0x1403, 0x0000, 0x0800, 0xd200, 0x9851, 0xb046, 0xdac4, 0x1b2c,
369 0x0001, 0x8800, 0x041f, 0x0600, 0x1800, 0x0000, 0x0000, 0x0100,
370 0x0000, 0xa000, 0x0081, 0x0000, 0x6100, 0x2e62, 0x7874, 0x5574,
371 0x0554, 0x0300, 0x097c, 0x553a, 0x7875, 0x000b, 0x0401, 0x4289,
372 0x0000, 0x8804, 0x0013, 0x5000, 0x054b, 0x0006, 0x0000, 0x0100,
373 0x0100, 0x4c00, 0x0000, 0x5b00, 0x0001, 0x0000, 0x0000
374};
375
376static const uint8_t kAbTxtName[] = { 'a', 'b', '.', 't', 'x', 't' };
377static const uint16_t kAbTxtNameLength = sizeof(kAbTxtName);
378static const size_t kAbUncompressedSize = 270216;
379
Narayan Kamath926973e2014-06-09 14:18:14 +0100380static int make_temporary_file(const char* file_name_pattern) {
381 char full_path[1024];
382 // Account for differences between the host and the target.
383 //
384 // TODO: Maybe reuse bionic/tests/TemporaryFile.h.
385 snprintf(full_path, sizeof(full_path), "/data/local/tmp/%s", file_name_pattern);
386 int fd = mkstemp(full_path);
387 if (fd == -1) {
388 snprintf(full_path, sizeof(full_path), "/tmp/%s", file_name_pattern);
389 fd = mkstemp(full_path);
390 }
391
392 return fd;
393}
394
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100395TEST(ziparchive, EmptyEntries) {
396 char temp_file_pattern[] = "empty_entries_test_XXXXXX";
Narayan Kamath926973e2014-06-09 14:18:14 +0100397 int fd = make_temporary_file(temp_file_pattern);
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100398 ASSERT_NE(-1, fd);
399 const ssize_t file_size = sizeof(kEmptyEntriesZip);
400 ASSERT_EQ(file_size, TEMP_FAILURE_RETRY(write(fd, kEmptyEntriesZip, file_size)));
Narayan Kamath48953a12014-01-24 12:32:39 +0000401
402 ZipArchiveHandle handle;
403 ASSERT_EQ(0, OpenArchiveFd(fd, "EmptyEntriesTest", &handle));
404
405 ZipEntry entry;
Yusuke Sato07447542015-06-25 14:39:19 -0700406 ZipString empty_name;
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100407 empty_name.name = kEmptyTxtName;
408 empty_name.name_length = kEmptyTxtNameLength;
409 ASSERT_EQ(0, FindEntry(handle, empty_name, &entry));
Narayan Kamath48953a12014-01-24 12:32:39 +0000410 ASSERT_EQ(static_cast<uint32_t>(0), entry.uncompressed_length);
411 uint8_t buffer[1];
412 ASSERT_EQ(0, ExtractToMemory(handle, &entry, buffer, 1));
413
414 char output_file_pattern[] = "empty_entries_output_XXXXXX";
Narayan Kamath926973e2014-06-09 14:18:14 +0100415 int output_fd = make_temporary_file(output_file_pattern);
Narayan Kamath48953a12014-01-24 12:32:39 +0000416 ASSERT_NE(-1, output_fd);
417 ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, output_fd));
418
419 struct stat stat_buf;
420 ASSERT_EQ(0, fstat(output_fd, &stat_buf));
421 ASSERT_EQ(0, stat_buf.st_size);
422
423 close(fd);
424 close(output_fd);
425}
426
Narayan Kamathf899bd52015-04-17 11:53:14 +0100427TEST(ziparchive, EntryLargerThan32K) {
428 char temp_file_pattern[] = "entry_larger_than_32k_test_XXXXXX";
429 int fd = make_temporary_file(temp_file_pattern);
430 ASSERT_NE(-1, fd);
431 ASSERT_TRUE(android::base::WriteFully(fd, reinterpret_cast<const uint8_t*>(kAbZip),
432 sizeof(kAbZip) - 1));
433 ZipArchiveHandle handle;
434 ASSERT_EQ(0, OpenArchiveFd(fd, "EntryLargerThan32KTest", &handle));
435
436 ZipEntry entry;
Yusuke Sato07447542015-06-25 14:39:19 -0700437 ZipString ab_name;
Narayan Kamathf899bd52015-04-17 11:53:14 +0100438 ab_name.name = kAbTxtName;
439 ab_name.name_length = kAbTxtNameLength;
440 ASSERT_EQ(0, FindEntry(handle, ab_name, &entry));
441 ASSERT_EQ(kAbUncompressedSize, entry.uncompressed_length);
442
443 // Extract the entry to memory.
444 std::vector<uint8_t> buffer(kAbUncompressedSize);
445 ASSERT_EQ(0, ExtractToMemory(handle, &entry, &buffer[0], buffer.size()));
446
447 // Extract the entry to a file.
448 char output_file_pattern[] = "entry_larger_than_32k_test_output_XXXXXX";
449 int output_fd = make_temporary_file(output_file_pattern);
450 ASSERT_NE(-1, output_fd);
451 ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, output_fd));
452
453 // Make sure the extracted file size is as expected.
454 struct stat stat_buf;
455 ASSERT_EQ(0, fstat(output_fd, &stat_buf));
456 ASSERT_EQ(kAbUncompressedSize, static_cast<size_t>(stat_buf.st_size));
457
458 // Read the file back to a buffer and make sure the contents are
459 // the same as the memory buffer we extracted directly to.
460 std::vector<uint8_t> file_contents(kAbUncompressedSize);
461 ASSERT_EQ(0, lseek64(output_fd, 0, SEEK_SET));
462 ASSERT_TRUE(android::base::ReadFully(output_fd, &file_contents[0], file_contents.size()));
463 ASSERT_EQ(file_contents, buffer);
464
465 for (int i = 0; i < 90072; ++i) {
466 const uint8_t* line = &file_contents[0] + (3 * i);
467 ASSERT_EQ('a', line[0]);
468 ASSERT_EQ('b', line[1]);
469 ASSERT_EQ('\n', line[2]);
470 }
471
472 close(fd);
473 close(output_fd);
474}
475
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100476TEST(ziparchive, TrailerAfterEOCD) {
477 char temp_file_pattern[] = "trailer_after_eocd_test_XXXXXX";
Narayan Kamath926973e2014-06-09 14:18:14 +0100478 int fd = make_temporary_file(temp_file_pattern);
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100479 ASSERT_NE(-1, fd);
480
481 // Create a file with 8 bytes of random garbage.
482 static const uint8_t trailer[] = { 'A' ,'n', 'd', 'r', 'o', 'i', 'd', 'z' };
483 const ssize_t file_size = sizeof(kEmptyEntriesZip);
484 const ssize_t trailer_size = sizeof(trailer);
485 ASSERT_EQ(file_size, TEMP_FAILURE_RETRY(write(fd, kEmptyEntriesZip, file_size)));
486 ASSERT_EQ(trailer_size, TEMP_FAILURE_RETRY(write(fd, trailer, trailer_size)));
487
488 ZipArchiveHandle handle;
489 ASSERT_GT(0, OpenArchiveFd(fd, "EmptyEntriesTest", &handle));
490}
491
Narayan Kamath00a258c2013-12-13 16:06:19 +0000492TEST(ziparchive, ExtractToFile) {
Narayan Kamath48953a12014-01-24 12:32:39 +0000493 char kTempFilePattern[] = "zip_archive_input_XXXXXX";
Narayan Kamath926973e2014-06-09 14:18:14 +0100494 int fd = make_temporary_file(kTempFilePattern);
Narayan Kamath00a258c2013-12-13 16:06:19 +0000495 ASSERT_NE(-1, fd);
496 const uint8_t data[8] = { '1', '2', '3', '4', '5', '6', '7', '8' };
497 const ssize_t data_size = sizeof(data);
498
499 ASSERT_EQ(data_size, TEMP_FAILURE_RETRY(write(fd, data, data_size)));
500
501 ZipArchiveHandle handle;
502 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
503
504 ZipEntry entry;
Yusuke Sato07447542015-06-25 14:39:19 -0700505 ZipString name;
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100506 name.name = kATxtName;
507 name.name_length = kATxtNameLength;
508 ASSERT_EQ(0, FindEntry(handle, name, &entry));
Narayan Kamath00a258c2013-12-13 16:06:19 +0000509 ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, fd));
510
511
512 // Assert that the first 8 bytes of the file haven't been clobbered.
513 uint8_t read_buffer[data_size];
514 ASSERT_EQ(0, lseek64(fd, 0, SEEK_SET));
515 ASSERT_EQ(data_size, TEMP_FAILURE_RETRY(read(fd, read_buffer, data_size)));
516 ASSERT_EQ(0, memcmp(read_buffer, data, data_size));
517
518 // Assert that the remainder of the file contains the incompressed data.
519 std::vector<uint8_t> uncompressed_data(entry.uncompressed_length);
520 ASSERT_EQ(static_cast<ssize_t>(entry.uncompressed_length),
521 TEMP_FAILURE_RETRY(
522 read(fd, &uncompressed_data[0], entry.uncompressed_length)));
523 ASSERT_EQ(0, memcmp(&uncompressed_data[0], kATxtContents,
524 sizeof(kATxtContents)));
525
526 // Assert that the total length of the file is sane
Ying Wangcf86e2f2014-05-15 20:06:40 -0700527 ASSERT_EQ(data_size + static_cast<ssize_t>(sizeof(kATxtContents)),
528 lseek64(fd, 0, SEEK_END));
Narayan Kamath00a258c2013-12-13 16:06:19 +0000529
530 close(fd);
531}
532
Narayan Kamath58aaf462013-12-10 16:47:14 +0000533int main(int argc, char** argv) {
534 ::testing::InitGoogleTest(&argc, argv);
535
536 static struct option options[] = {
537 { "test_data_dir", required_argument, NULL, 't' },
538 { NULL, 0, NULL, 0 }
539 };
540
541 while (true) {
542 int option_index;
543 const int c = getopt_long_only(argc, argv, "", options, &option_index);
544 if (c == -1) {
545 break;
546 }
547
548 if (c == 't') {
549 test_data_dir = optarg;
550 }
Narayan Kamath7462f022013-11-21 13:05:04 +0000551 }
552
Narayan Kamath58aaf462013-12-10 16:47:14 +0000553 if (test_data_dir.size() == 0) {
554 printf("Test data flag (--test_data_dir) required\n\n");
555 return -1;
556 }
Narayan Kamath7462f022013-11-21 13:05:04 +0000557
Narayan Kamath58aaf462013-12-10 16:47:14 +0000558 if (test_data_dir[0] != '/') {
559 printf("Test data must be an absolute path, was %s\n\n",
560 test_data_dir.c_str());
561 return -2;
562 }
Narayan Kamath7462f022013-11-21 13:05:04 +0000563
Narayan Kamath58aaf462013-12-10 16:47:14 +0000564 return RUN_ALL_TESTS();
Narayan Kamath7462f022013-11-21 13:05:04 +0000565}