2 * Copyright (c) 2003-2007 Tim Kientzle
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 __FBSDID("$FreeBSD$");
35 struct contents archive_contents_sparse[] = {
41 struct contents archive_contents_sparse2[] = {
100 { 59000000, 1, "a" },
101 { 60000000, 1, "a" },
102 { 61000000, 1, "a" },
103 { 62000000, 1, "a" },
104 { 63000000, 1, "a" },
105 { 64000000, 1, "a" },
106 { 65000000, 1, "a" },
107 { 66000000, 1, "a" },
108 { 67000000, 1, "a" },
109 { 68000000, 1, "a" },
110 { 69000000, 1, "a" },
111 { 70000000, 1, "a" },
112 { 71000000, 1, "a" },
113 { 72000000, 1, "a" },
114 { 73000000, 1, "a" },
115 { 74000000, 1, "a" },
116 { 75000000, 1, "a" },
117 { 76000000, 1, "a" },
118 { 77000000, 1, "a" },
119 { 78000000, 1, "a" },
120 { 79000000, 1, "a" },
121 { 80000000, 1, "a" },
122 { 81000000, 1, "a" },
123 { 82000000, 1, "a" },
124 { 83000000, 1, "a" },
125 { 84000000, 1, "a" },
126 { 85000000, 1, "a" },
127 { 86000000, 1, "a" },
128 { 87000000, 1, "a" },
129 { 88000000, 1, "a" },
130 { 89000000, 1, "a" },
131 { 90000000, 1, "a" },
132 { 91000000, 1, "a" },
133 { 92000000, 1, "a" },
134 { 93000000, 1, "a" },
135 { 94000000, 1, "a" },
136 { 95000000, 1, "a" },
137 { 96000000, 1, "a" },
138 { 97000000, 1, "a" },
139 { 98000000, 1, "a" },
140 { 99000000, 1, "a" },
141 { 99000001, 0, NULL }
144 struct contents archive_contents_nonsparse[] = {
150 * Describe an archive with three entries:
152 * File 1: named "sparse"
153 * * a length of 3145728 bytes (3MiB)
154 * * a single 'a' byte at offset 1000000
155 * * a single 'a' byte at offset 2000000
156 * File 2: named "sparse2"
157 * * a single 'a' byte at offset 1,000,000, 2,000,000, ..., 99,000,000
158 * * length of 99,000,001
159 * File 3: named 'non-sparse'
161 * * contains a single byte 'a'
164 struct archive_contents {
165 const char *filename;
166 struct contents *contents;
168 { "sparse", archive_contents_sparse },
169 { "sparse2", archive_contents_sparse2 },
170 { "non-sparse", archive_contents_nonsparse },
175 * A tricky piece of code that verifies the contents of a sparse
176 * archive entry against a description as defined at the top of this
179 #define min(a,b) ((a) < (b) ? (a) : (b))
182 verify_archive_file(const char *name, struct archive_contents *ac)
184 struct archive_entry *ae;
186 /* data, size, offset of next expected block. */
187 struct contents expect;
188 /* data, size, offset of block read from archive. */
189 struct contents actual;
192 extract_reference_file(name);
194 assert((a = archive_read_new()) != NULL);
195 assert(0 == archive_read_support_compression_all(a));
196 assert(0 == archive_read_support_format_tar(a));
197 failure("Can't open %s", name);
198 assert(0 == archive_read_open_filename(a, name, 3));
200 while (ac->filename != NULL) {
201 struct contents *cts = ac->contents;
203 assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
204 failure("Name mismatch in archive %s", name);
205 assertEqualString(ac->filename, archive_entry_pathname(ae));
208 while (0 == (err = archive_read_data_block(a,
209 (const void **)&actual.d,
210 &actual.s, &actual.o))) {
211 while (actual.s > 0) {
212 char c = *(const char *)actual.d;
213 if(actual.o < expect.o) {
215 * Any byte before the expected
218 failure("%s: pad at offset %d "
219 "should be zero", name, actual.o);
220 assertEqualInt(c, 0);
221 } else if (actual.o == expect.o) {
223 * Data at matching offsets must match.
225 assertEqualInt(c, *expect.d);
229 /* End of expected? step to next expected. */
234 * We found data beyond that expected.
236 failure("%s: Unexpected trailing data",
238 assert(actual.o <= expect.o);
239 archive_read_finish(a);
247 failure("%s: should be end of entry", name);
248 assertEqualIntA(a, err, ARCHIVE_EOF);
249 failure("%s: Size returned at EOF must be zero", name);
250 assertEqualInt(actual.s, 0);
251 #if ARCHIVE_VERSION_NUMBER < 1009000
252 /* libarchive < 1.9 doesn't get this right */
253 skipping("offset of final sparse chunk");
255 failure("%s: Offset of final empty chunk must be same as file size", name);
256 assertEqualInt(actual.o, expect.o);
258 /* Step to next file description. */
262 err = archive_read_next_header(a, &ae);
263 assertEqualIntA(a, ARCHIVE_EOF, err);
265 assert(0 == archive_read_close(a));
266 #if ARCHIVE_VERSION_NUMBER < 2000000
267 archive_read_finish(a);
269 assert(0 == archive_read_finish(a));
274 DEFINE_TEST(test_read_format_gtar_sparse)
276 /* Two archives that use the "GNU tar sparse format". */
277 verify_archive_file("test_read_format_gtar_sparse_1_13.tgz", files);
278 verify_archive_file("test_read_format_gtar_sparse_1_17.tgz", files);
281 * libarchive < 1.9 doesn't support the newer --posix sparse formats
282 * from GNU tar 1.15 and later.
284 #if ARCHIVE_VERSION_NUMBER < 1009000
285 skipping("read support for GNUtar --posix sparse formats");
288 * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1
291 "test_read_format_gtar_sparse_1_17_posix00.tgz",
294 * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1
297 "test_read_format_gtar_sparse_1_17_posix01.tgz",
300 * An archive created by GNU tar 1.17 using --posix --sparse-format=1.0
303 "test_read_format_gtar_sparse_1_17_posix10.tgz",
306 * The last test archive here is a little odd. First, it's
307 * uncompressed, because that exercises some of the block
308 * reassembly code a little harder. Second, it includes some
309 * leading comments prior to the sparse block description.
310 * GNU tar doesn't do this, but I think it should, so I want
311 * to ensure that libarchive correctly ignores such comments.
312 * Dump the file, looking for "#!gnu-sparse-format" starting
316 "test_read_format_gtar_sparse_1_17_posix10_modified.tar",