1228753Smm/*-
2228753Smm * Copyright (c) 2003-2007 Tim Kientzle
3232153Smm * Copyright (c) 2011 Michihiro NAKAJIMA
4228753Smm * All rights reserved.
5228753Smm *
6228753Smm * Redistribution and use in source and binary forms, with or without
7228753Smm * modification, are permitted provided that the following conditions
8228753Smm * are met:
9228753Smm * 1. Redistributions of source code must retain the above copyright
10228753Smm *    notice, this list of conditions and the following disclaimer.
11228753Smm * 2. Redistributions in binary form must reproduce the above copyright
12228753Smm *    notice, this list of conditions and the following disclaimer in the
13228753Smm *    documentation and/or other materials provided with the distribution.
14228753Smm *
15228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25228753Smm */
26228753Smm#include "test.h"
27228763Smm__FBSDID("$FreeBSD$");
28228753Smm
29232153Smm#ifdef HAVE_LIBZ
30232153Smmstatic const int libz_enabled = 1;
31232153Smm#else
32232153Smmstatic const int libz_enabled = 0;
33232153Smm#endif
34232153Smm
35228753Smm/*
36228753Smm * The reference file for this has been manually tweaked so that:
37228753Smm *   * file2 has length-at-end but file1 does not
38228753Smm *   * file2 has an invalid CRC
39228753Smm */
40232153Smmstatic void
41232153Smmverify_basic(struct archive *a, int seek_checks)
42228753Smm{
43228753Smm	struct archive_entry *ae;
44228753Smm	char *buff[128];
45228753Smm	const void *pv;
46228753Smm	size_t s;
47232153Smm	int64_t o;
48228753Smm
49232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
50228753Smm	assertEqualString("dir/", archive_entry_pathname(ae));
51228753Smm	assertEqualInt(1179604249, archive_entry_mtime(ae));
52228753Smm	assertEqualInt(0, archive_entry_size(ae));
53232153Smm	if (seek_checks)
54232153Smm		assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae));
55228753Smm	assertEqualIntA(a, ARCHIVE_EOF,
56228753Smm	    archive_read_data_block(a, &pv, &s, &o));
57228753Smm	assertEqualInt((int)s, 0);
58232153Smm
59232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
60228753Smm	assertEqualString("file1", archive_entry_pathname(ae));
61228753Smm	assertEqualInt(1179604289, archive_entry_mtime(ae));
62232153Smm	if (seek_checks)
63232153Smm		assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae));
64228753Smm	assertEqualInt(18, archive_entry_size(ae));
65228753Smm	failure("archive_read_data() returns number of bytes read");
66232153Smm	if (libz_enabled) {
67232153Smm		assertEqualInt(18, archive_read_data(a, buff, 19));
68232153Smm		assertEqualMem(buff, "hello\nhello\nhello\n", 18);
69232153Smm	} else {
70232153Smm		assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, 19));
71232153Smm		assertEqualString(archive_error_string(a),
72232153Smm		    "Unsupported ZIP compression method (deflation)");
73232153Smm		assert(archive_errno(a) != 0);
74228753Smm	}
75232153Smm
76232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
77228753Smm	assertEqualString("file2", archive_entry_pathname(ae));
78228753Smm	assertEqualInt(1179605932, archive_entry_mtime(ae));
79232153Smm	if (seek_checks) {
80232153Smm		assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae));
81232153Smm		assertEqualInt(64, archive_entry_size_is_set(ae));
82232153Smm	} else {
83232153Smm		failure("file2 has length-at-end, so we shouldn't see a valid size when streaming");
84232153Smm		assertEqualInt(0, archive_entry_size_is_set(ae));
85232153Smm	}
86232153Smm	if (libz_enabled) {
87232153Smm		failure("file2 has a bad CRC, so read should fail and not change buff");
88232153Smm		memset(buff, 'a', 19);
89232153Smm		assertEqualInt(ARCHIVE_WARN, archive_read_data(a, buff, 19));
90232153Smm		assertEqualMem(buff, "aaaaaaaaaaaaaaaaaaa", 19);
91232153Smm	} else {
92232153Smm		assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, 19));
93232153Smm		assertEqualString(archive_error_string(a),
94232153Smm		    "Unsupported ZIP compression method (deflation)");
95232153Smm		assert(archive_errno(a) != 0);
96232153Smm	}
97232153Smm	assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae));
98232153Smm	/* Verify the number of files read. */
99232153Smm	failure("the archive file has three files");
100232153Smm	assertEqualInt(3, archive_file_count(a));
101248616Smm	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
102232153Smm	assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a));
103232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
104232153Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
105228753Smm}
106228753Smm
107232153Smmstatic void
108232153Smmtest_basic(void)
109232153Smm{
110232153Smm	const char *refname = "test_read_format_zip.zip";
111232153Smm	struct archive *a;
112232153Smm	char *p;
113232153Smm	size_t s;
114228753Smm
115232153Smm	extract_reference_file(refname);
116232153Smm
117232153Smm	/* Verify with seeking reader. */
118232153Smm	assert((a = archive_read_new()) != NULL);
119232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
120232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
121232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240));
122232153Smm	verify_basic(a, 1);
123232153Smm
124232153Smm	/* Verify with streaming reader. */
125232153Smm	p = slurpfile(&s, refname);
126232153Smm	assert((a = archive_read_new()) != NULL);
127232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
128232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
129232153Smm	assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 31));
130232153Smm	verify_basic(a, 0);
131232153Smm}
132232153Smm
133232153Smm/*
134232153Smm * Read Info-ZIP New Unix Extra Field 0x7875 "ux".
135232153Smm *  Currently stores Unix UID/GID up to 32 bits.
136232153Smm */
137232153Smmstatic void
138232153Smmverify_info_zip_ux(struct archive *a, int seek_checks)
139232153Smm{
140232153Smm	struct archive_entry *ae;
141232153Smm	char *buff[128];
142232153Smm
143232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
144232153Smm	assertEqualString("file1", archive_entry_pathname(ae));
145232153Smm	assertEqualInt(1300668680, archive_entry_mtime(ae));
146232153Smm	assertEqualInt(18, archive_entry_size(ae));
147232153Smm	if (seek_checks)
148232153Smm		assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae));
149232153Smm	failure("zip reader should read Info-ZIP New Unix Extra Field");
150232153Smm	assertEqualInt(1001, archive_entry_uid(ae));
151232153Smm	assertEqualInt(1001, archive_entry_gid(ae));
152232153Smm	if (libz_enabled) {
153232153Smm		failure("archive_read_data() returns number of bytes read");
154232153Smm		assertEqualInt(18, archive_read_data(a, buff, 19));
155232153Smm		assertEqualMem(buff, "hello\nhello\nhello\n", 18);
156232153Smm	} else {
157232153Smm		assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, 19));
158232153Smm		assertEqualString(archive_error_string(a),
159232153Smm		    "Unsupported ZIP compression method (deflation)");
160232153Smm		assert(archive_errno(a) != 0);
161232153Smm	}
162232153Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
163232153Smm
164232153Smm	/* Verify the number of files read. */
165232153Smm	failure("the archive file has just one file");
166232153Smm	assertEqualInt(1, archive_file_count(a));
167232153Smm
168248616Smm	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
169232153Smm	assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a));
170232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
171232153Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
172232153Smm}
173232153Smm
174232153Smmstatic void
175232153Smmtest_info_zip_ux(void)
176232153Smm{
177232153Smm	const char *refname = "test_read_format_zip_ux.zip";
178232153Smm	struct archive *a;
179232153Smm	char *p;
180232153Smm	size_t s;
181232153Smm
182232153Smm	extract_reference_file(refname);
183232153Smm
184232153Smm	/* Verify with seeking reader. */
185232153Smm	assert((a = archive_read_new()) != NULL);
186232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
187232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
188232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240));
189232153Smm	verify_info_zip_ux(a, 1);
190232153Smm
191232153Smm	/* Verify with streaming reader. */
192232153Smm	p = slurpfile(&s, refname);
193232153Smm	assert((a = archive_read_new()) != NULL);
194232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
195232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
196232153Smm	assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 108));
197232153Smm	verify_info_zip_ux(a, 0);
198232153Smm}
199232153Smm
200232153Smm/*
201232153Smm * Verify that test_read_extract correctly works with
202232153Smm * Zip entries that use length-at-end.
203232153Smm */
204232153Smmstatic void
205232153Smmverify_extract_length_at_end(struct archive *a, int seek_checks)
206232153Smm{
207232153Smm	struct archive_entry *ae;
208232153Smm
209232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
210232153Smm
211232153Smm	assertEqualString("hello.txt", archive_entry_pathname(ae));
212232153Smm	if (seek_checks) {
213232153Smm		assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae));
214232153Smm		assert(archive_entry_size_is_set(ae));
215232153Smm		assertEqualInt(6, archive_entry_size(ae));
216232153Smm	} else {
217232153Smm		assert(!archive_entry_size_is_set(ae));
218232153Smm		assertEqualInt(0, archive_entry_size(ae));
219232153Smm	}
220232153Smm
221232153Smm	if (libz_enabled) {
222232153Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_extract(a, ae, 0));
223232153Smm		assertFileContents("hello\x0A", 6, "hello.txt");
224232153Smm	} else {
225232153Smm		assertEqualIntA(a, ARCHIVE_FAILED, archive_read_extract(a, ae, 0));
226232153Smm		assertEqualString(archive_error_string(a),
227232153Smm		    "Unsupported ZIP compression method (deflation)");
228232153Smm		assert(archive_errno(a) != 0);
229232153Smm	}
230232153Smm
231232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
232232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
233232153Smm}
234232153Smm
235232153Smmstatic void
236232153Smmtest_extract_length_at_end(void)
237232153Smm{
238232153Smm	const char *refname = "test_read_format_zip_length_at_end.zip";
239232153Smm	char *p;
240232153Smm	size_t s;
241232153Smm	struct archive *a;
242232153Smm
243232153Smm	extract_reference_file(refname);
244232153Smm
245232153Smm	/* Verify extraction with seeking reader. */
246232153Smm	assert((a = archive_read_new()) != NULL);
247232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
248232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
249232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240));
250232153Smm	verify_extract_length_at_end(a, 1);
251232153Smm
252232153Smm	/* Verify extraction with streaming reader. */
253232153Smm	p = slurpfile(&s, refname);
254232153Smm	assert((a = archive_read_new()) != NULL);
255232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
256232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
257232153Smm	assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 108));
258232153Smm	verify_extract_length_at_end(a, 0);
259232153Smm}
260232153Smm
261232153Smmstatic void
262232153Smmtest_symlink(void)
263232153Smm{
264232153Smm	const char *refname = "test_read_format_zip_symlink.zip";
265232153Smm	char *p;
266232153Smm	size_t s;
267232153Smm	struct archive *a;
268232153Smm	struct archive_entry *ae;
269232153Smm
270232153Smm	extract_reference_file(refname);
271232153Smm	p = slurpfile(&s, refname);
272232153Smm
273232153Smm	/* Symlinks can only be extracted with the seeking reader. */
274232153Smm	assert((a = archive_read_new()) != NULL);
275232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
276232153Smm	assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 1));
277232153Smm
278232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
279232153Smm	assertEqualString("file", archive_entry_pathname(ae));
280232153Smm	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
281232153Smm
282232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
283232153Smm	assertEqualString("symlink", archive_entry_pathname(ae));
284232153Smm	assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
285232153Smm	assertEqualInt(0, archive_entry_size(ae));
286232153Smm	assertEqualString("file", archive_entry_symlink(ae));
287232153Smm
288232153Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
289232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
290232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
291232153Smm}
292232153Smm
293232153SmmDEFINE_TEST(test_read_format_zip)
294232153Smm{
295232153Smm	test_basic();
296232153Smm	test_info_zip_ux();
297232153Smm	test_extract_length_at_end();
298232153Smm	test_symlink();
299232153Smm}
300