1228753Smm/*-
2228753Smm * Copyright (c) 2003-2007 Tim Kientzle
3228753Smm * All rights reserved.
4228753Smm *
5228753Smm * Redistribution and use in source and binary forms, with or without
6228753Smm * modification, are permitted provided that the following conditions
7228753Smm * are met:
8228753Smm * 1. Redistributions of source code must retain the above copyright
9228753Smm *    notice, this list of conditions and the following disclaimer.
10228753Smm * 2. Redistributions in binary form must reproduce the above copyright
11228753Smm *    notice, this list of conditions and the following disclaimer in the
12228753Smm *    documentation and/or other materials provided with the distribution.
13228753Smm *
14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24228753Smm */
25228753Smm#include "test.h"
26228763Smm__FBSDID("$FreeBSD: stable/11/contrib/libarchive/libarchive/test/test_read_format_gtar_sparse.c 358088 2020-02-19 01:50:47Z mm $");
27228753Smm
28228753Smm
29228753Smmstruct contents {
30232153Smm	int64_t	o;
31228753Smm	size_t	s;
32228753Smm	const char *d;
33228753Smm};
34228753Smm
35228753Smmstruct contents archive_contents_sparse[] = {
36228753Smm	{ 1000000, 1, "a" },
37228753Smm	{ 2000000, 1, "a" },
38228753Smm	{ 3145728, 0, NULL }
39228753Smm};
40228753Smm
41228753Smmstruct contents archive_contents_sparse2[] = {
42228753Smm	{ 1000000, 1, "a" },
43228753Smm	{ 2000000, 1, "a" },
44228753Smm	{ 3000000, 1, "a" },
45228753Smm	{ 4000000, 1, "a" },
46228753Smm	{ 5000000, 1, "a" },
47228753Smm	{ 6000000, 1, "a" },
48228753Smm	{ 7000000, 1, "a" },
49228753Smm	{ 8000000, 1, "a" },
50228753Smm	{ 9000000, 1, "a" },
51228753Smm	{ 10000000, 1, "a" },
52228753Smm	{ 11000000, 1, "a" },
53228753Smm	{ 12000000, 1, "a" },
54228753Smm	{ 13000000, 1, "a" },
55228753Smm	{ 14000000, 1, "a" },
56228753Smm	{ 15000000, 1, "a" },
57228753Smm	{ 16000000, 1, "a" },
58228753Smm	{ 17000000, 1, "a" },
59228753Smm	{ 18000000, 1, "a" },
60228753Smm	{ 19000000, 1, "a" },
61228753Smm	{ 20000000, 1, "a" },
62228753Smm	{ 21000000, 1, "a" },
63228753Smm	{ 22000000, 1, "a" },
64228753Smm	{ 23000000, 1, "a" },
65228753Smm	{ 24000000, 1, "a" },
66228753Smm	{ 25000000, 1, "a" },
67228753Smm	{ 26000000, 1, "a" },
68228753Smm	{ 27000000, 1, "a" },
69228753Smm	{ 28000000, 1, "a" },
70228753Smm	{ 29000000, 1, "a" },
71228753Smm	{ 30000000, 1, "a" },
72228753Smm	{ 31000000, 1, "a" },
73228753Smm	{ 32000000, 1, "a" },
74228753Smm	{ 33000000, 1, "a" },
75228753Smm	{ 34000000, 1, "a" },
76228753Smm	{ 35000000, 1, "a" },
77228753Smm	{ 36000000, 1, "a" },
78228753Smm	{ 37000000, 1, "a" },
79228753Smm	{ 38000000, 1, "a" },
80228753Smm	{ 39000000, 1, "a" },
81228753Smm	{ 40000000, 1, "a" },
82228753Smm	{ 41000000, 1, "a" },
83228753Smm	{ 42000000, 1, "a" },
84228753Smm	{ 43000000, 1, "a" },
85228753Smm	{ 44000000, 1, "a" },
86228753Smm	{ 45000000, 1, "a" },
87228753Smm	{ 46000000, 1, "a" },
88228753Smm	{ 47000000, 1, "a" },
89228753Smm	{ 48000000, 1, "a" },
90228753Smm	{ 49000000, 1, "a" },
91228753Smm	{ 50000000, 1, "a" },
92228753Smm	{ 51000000, 1, "a" },
93228753Smm	{ 52000000, 1, "a" },
94228753Smm	{ 53000000, 1, "a" },
95228753Smm	{ 54000000, 1, "a" },
96228753Smm	{ 55000000, 1, "a" },
97228753Smm	{ 56000000, 1, "a" },
98228753Smm	{ 57000000, 1, "a" },
99228753Smm	{ 58000000, 1, "a" },
100228753Smm	{ 59000000, 1, "a" },
101228753Smm	{ 60000000, 1, "a" },
102228753Smm	{ 61000000, 1, "a" },
103228753Smm	{ 62000000, 1, "a" },
104228753Smm	{ 63000000, 1, "a" },
105228753Smm	{ 64000000, 1, "a" },
106228753Smm	{ 65000000, 1, "a" },
107228753Smm	{ 66000000, 1, "a" },
108228753Smm	{ 67000000, 1, "a" },
109228753Smm	{ 68000000, 1, "a" },
110228753Smm	{ 69000000, 1, "a" },
111228753Smm	{ 70000000, 1, "a" },
112228753Smm	{ 71000000, 1, "a" },
113228753Smm	{ 72000000, 1, "a" },
114228753Smm	{ 73000000, 1, "a" },
115228753Smm	{ 74000000, 1, "a" },
116228753Smm	{ 75000000, 1, "a" },
117228753Smm	{ 76000000, 1, "a" },
118228753Smm	{ 77000000, 1, "a" },
119228753Smm	{ 78000000, 1, "a" },
120228753Smm	{ 79000000, 1, "a" },
121228753Smm	{ 80000000, 1, "a" },
122228753Smm	{ 81000000, 1, "a" },
123228753Smm	{ 82000000, 1, "a" },
124228753Smm	{ 83000000, 1, "a" },
125228753Smm	{ 84000000, 1, "a" },
126228753Smm	{ 85000000, 1, "a" },
127228753Smm	{ 86000000, 1, "a" },
128228753Smm	{ 87000000, 1, "a" },
129228753Smm	{ 88000000, 1, "a" },
130228753Smm	{ 89000000, 1, "a" },
131228753Smm	{ 90000000, 1, "a" },
132228753Smm	{ 91000000, 1, "a" },
133228753Smm	{ 92000000, 1, "a" },
134228753Smm	{ 93000000, 1, "a" },
135228753Smm	{ 94000000, 1, "a" },
136228753Smm	{ 95000000, 1, "a" },
137228753Smm	{ 96000000, 1, "a" },
138228753Smm	{ 97000000, 1, "a" },
139228753Smm	{ 98000000, 1, "a" },
140228753Smm	{ 99000000, 1, "a" },
141228753Smm	{ 99000001, 0, NULL }
142228753Smm};
143228753Smm
144228753Smmstruct contents archive_contents_nonsparse[] = {
145228753Smm	{ 0, 1, "a" },
146228753Smm	{ 1, 0, NULL }
147228753Smm};
148228753Smm
149228753Smm/*
150228753Smm * Describe an archive with three entries:
151228753Smm *
152228753Smm * File 1: named "sparse"
153228753Smm *   * a length of 3145728 bytes (3MiB)
154228753Smm *   * a single 'a' byte at offset 1000000
155228753Smm *   * a single 'a' byte at offset 2000000
156228753Smm * File 2: named "sparse2"
157228753Smm *   * a single 'a' byte at offset 1,000,000, 2,000,000, ..., 99,000,000
158228753Smm *   * length of 99,000,001
159228753Smm * File 3: named 'non-sparse'
160228753Smm *   * length of 1 byte
161228753Smm *   * contains a single byte 'a'
162228753Smm */
163228753Smm
164228753Smmstruct archive_contents {
165228753Smm	const char *filename;
166228753Smm	struct contents *contents;
167228753Smm} files[] = {
168228753Smm	{ "sparse", archive_contents_sparse },
169228753Smm	{ "sparse2", archive_contents_sparse2 },
170228753Smm	{ "non-sparse", archive_contents_nonsparse },
171228753Smm	{ NULL, NULL }
172228753Smm};
173228753Smm
174228753Smmstatic void
175228753Smmverify_archive_file(const char *name, struct archive_contents *ac)
176228753Smm{
177228753Smm	struct archive_entry *ae;
178228753Smm	int err;
179228753Smm	/* data, size, offset of next expected block. */
180228753Smm	struct contents expect;
181228753Smm	/* data, size, offset of block read from archive. */
182228753Smm	struct contents actual;
183228753Smm	const void *p;
184228753Smm	struct archive *a;
185228753Smm
186228753Smm	extract_reference_file(name);
187228753Smm
188228753Smm	assert((a = archive_read_new()) != NULL);
189232153Smm	assert(0 == archive_read_support_filter_all(a));
190228753Smm	assert(0 == archive_read_support_format_tar(a));
191228753Smm	failure("Can't open %s", name);
192228753Smm	assert(0 == archive_read_open_filename(a, name, 3));
193228753Smm
194228753Smm	while (ac->filename != NULL) {
195228753Smm		struct contents *cts = ac->contents;
196228753Smm
197228753Smm		if (!assertEqualIntA(a, 0, archive_read_next_header(a, &ae))) {
198232153Smm			assertEqualInt(ARCHIVE_OK, archive_read_free(a));
199228753Smm			return;
200228753Smm		}
201228753Smm		failure("Name mismatch in archive %s", name);
202228753Smm		assertEqualString(ac->filename, archive_entry_pathname(ae));
203299529Smm		assertEqualInt(archive_entry_is_encrypted(ae), 0);
204299529Smm		assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
205228753Smm
206228753Smm		expect = *cts++;
207228753Smm		while (0 == (err = archive_read_data_block(a,
208228753Smm				 &p, &actual.s, &actual.o))) {
209228753Smm			actual.d = p;
210228753Smm			while (actual.s > 0) {
211228753Smm				char c = *actual.d;
212228753Smm				if(actual.o < expect.o) {
213228753Smm					/*
214228753Smm					 * Any byte before the expected
215228753Smm					 * data must be NULL.
216228753Smm					 */
217358088Smm					failure("%s: pad at offset %jd "
218358088Smm						"should be zero", name,
219358088Smm						(intmax_t)actual.o);
220228753Smm					assertEqualInt(c, 0);
221228753Smm				} else if (actual.o == expect.o) {
222228753Smm					/*
223228753Smm					 * Data at matching offsets must match.
224228753Smm					 */
225228753Smm					assertEqualInt(c, *expect.d);
226228753Smm					expect.d++;
227228753Smm					expect.o++;
228228753Smm					expect.s--;
229228753Smm					/* End of expected? step to next expected. */
230228753Smm					if (expect.s <= 0)
231228753Smm						expect = *cts++;
232228753Smm				} else {
233228753Smm					/*
234228753Smm					 * We found data beyond that expected.
235228753Smm					 */
236228753Smm					failure("%s: Unexpected trailing data",
237228753Smm					    name);
238228753Smm					assert(actual.o <= expect.o);
239232153Smm					archive_read_free(a);
240228753Smm					return;
241228753Smm				}
242228753Smm				actual.d++;
243228753Smm				actual.o++;
244228753Smm				actual.s--;
245228753Smm			}
246228753Smm		}
247228753Smm		failure("%s: should be end of entry", name);
248228753Smm		assertEqualIntA(a, err, ARCHIVE_EOF);
249228753Smm		failure("%s: Size returned at EOF must be zero", name);
250228753Smm		assertEqualInt((int)actual.s, 0);
251228753Smm		failure("%s: Offset of final empty chunk must be same as file size", name);
252228753Smm		assertEqualInt(actual.o, expect.o);
253228753Smm		/* Step to next file description. */
254228753Smm		++ac;
255228753Smm	}
256228753Smm
257228753Smm	err = archive_read_next_header(a, &ae);
258228753Smm	assertEqualIntA(a, ARCHIVE_EOF, err);
259228753Smm
260232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
261232153Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
262228753Smm}
263228753Smm
264228753Smm
265228753SmmDEFINE_TEST(test_read_format_gtar_sparse)
266228753Smm{
267228753Smm	/* Two archives that use the "GNU tar sparse format". */
268228753Smm	verify_archive_file("test_read_format_gtar_sparse_1_13.tar", files);
269228753Smm	verify_archive_file("test_read_format_gtar_sparse_1_17.tar", files);
270228753Smm
271228753Smm	/*
272228753Smm	 * libarchive < 1.9 doesn't support the newer --posix sparse formats
273228753Smm	 * from GNU tar 1.15 and later.
274228753Smm	 */
275232153Smm
276228753Smm	/*
277228753Smm	 * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1
278228753Smm	 */
279228753Smm	verify_archive_file(
280228753Smm		"test_read_format_gtar_sparse_1_17_posix00.tar",
281228753Smm		files);
282228753Smm	/*
283228753Smm	 * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1
284228753Smm	 */
285228753Smm	verify_archive_file(
286228753Smm		"test_read_format_gtar_sparse_1_17_posix01.tar",
287228753Smm		files);
288228753Smm	/*
289228753Smm	 * An archive created by GNU tar 1.17 using --posix --sparse-format=1.0
290228753Smm	 */
291228753Smm	verify_archive_file(
292228753Smm		"test_read_format_gtar_sparse_1_17_posix10.tar",
293228753Smm		files);
294228753Smm	/*
295228753Smm	 * The last test archive here is a little odd.  First, it's
296228753Smm	 * uncompressed, because that exercises some of the block
297228753Smm	 * reassembly code a little harder.  Second, it includes some
298228753Smm	 * leading comments prior to the sparse block description.
299228753Smm	 * GNU tar doesn't do this, but I think it should, so I want
300228753Smm	 * to ensure that libarchive correctly ignores such comments.
301228753Smm	 * Dump the file, looking for "#!gnu-sparse-format" starting
302228753Smm	 * at byte 0x600.
303228753Smm	 */
304228753Smm	verify_archive_file(
305228753Smm		"test_read_format_gtar_sparse_1_17_posix10_modified.tar",
306228753Smm		files);
307228753Smm}
308228753Smm
309228753Smm
310