1 /*-
2 * Copyright (c) 2003-2007 Tim Kientzle
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
13 *
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.
24 */
25 #include "test.h"
26
27 struct contents {
28 int64_t o;
29 size_t s;
30 const char *d;
31 };
32
33 static struct contents archive_contents_sparse[] = {
34 { 1000000, 1, "a" },
35 { 2000000, 1, "a" },
36 { 3145728, 0, NULL }
37 };
38
39 static struct contents archive_contents_sparse2[] = {
40 { 1000000, 1, "a" },
41 { 2000000, 1, "a" },
42 { 3000000, 1, "a" },
43 { 4000000, 1, "a" },
44 { 5000000, 1, "a" },
45 { 6000000, 1, "a" },
46 { 7000000, 1, "a" },
47 { 8000000, 1, "a" },
48 { 9000000, 1, "a" },
49 { 10000000, 1, "a" },
50 { 11000000, 1, "a" },
51 { 12000000, 1, "a" },
52 { 13000000, 1, "a" },
53 { 14000000, 1, "a" },
54 { 15000000, 1, "a" },
55 { 16000000, 1, "a" },
56 { 17000000, 1, "a" },
57 { 18000000, 1, "a" },
58 { 19000000, 1, "a" },
59 { 20000000, 1, "a" },
60 { 21000000, 1, "a" },
61 { 22000000, 1, "a" },
62 { 23000000, 1, "a" },
63 { 24000000, 1, "a" },
64 { 25000000, 1, "a" },
65 { 26000000, 1, "a" },
66 { 27000000, 1, "a" },
67 { 28000000, 1, "a" },
68 { 29000000, 1, "a" },
69 { 30000000, 1, "a" },
70 { 31000000, 1, "a" },
71 { 32000000, 1, "a" },
72 { 33000000, 1, "a" },
73 { 34000000, 1, "a" },
74 { 35000000, 1, "a" },
75 { 36000000, 1, "a" },
76 { 37000000, 1, "a" },
77 { 38000000, 1, "a" },
78 { 39000000, 1, "a" },
79 { 40000000, 1, "a" },
80 { 41000000, 1, "a" },
81 { 42000000, 1, "a" },
82 { 43000000, 1, "a" },
83 { 44000000, 1, "a" },
84 { 45000000, 1, "a" },
85 { 46000000, 1, "a" },
86 { 47000000, 1, "a" },
87 { 48000000, 1, "a" },
88 { 49000000, 1, "a" },
89 { 50000000, 1, "a" },
90 { 51000000, 1, "a" },
91 { 52000000, 1, "a" },
92 { 53000000, 1, "a" },
93 { 54000000, 1, "a" },
94 { 55000000, 1, "a" },
95 { 56000000, 1, "a" },
96 { 57000000, 1, "a" },
97 { 58000000, 1, "a" },
98 { 59000000, 1, "a" },
99 { 60000000, 1, "a" },
100 { 61000000, 1, "a" },
101 { 62000000, 1, "a" },
102 { 63000000, 1, "a" },
103 { 64000000, 1, "a" },
104 { 65000000, 1, "a" },
105 { 66000000, 1, "a" },
106 { 67000000, 1, "a" },
107 { 68000000, 1, "a" },
108 { 69000000, 1, "a" },
109 { 70000000, 1, "a" },
110 { 71000000, 1, "a" },
111 { 72000000, 1, "a" },
112 { 73000000, 1, "a" },
113 { 74000000, 1, "a" },
114 { 75000000, 1, "a" },
115 { 76000000, 1, "a" },
116 { 77000000, 1, "a" },
117 { 78000000, 1, "a" },
118 { 79000000, 1, "a" },
119 { 80000000, 1, "a" },
120 { 81000000, 1, "a" },
121 { 82000000, 1, "a" },
122 { 83000000, 1, "a" },
123 { 84000000, 1, "a" },
124 { 85000000, 1, "a" },
125 { 86000000, 1, "a" },
126 { 87000000, 1, "a" },
127 { 88000000, 1, "a" },
128 { 89000000, 1, "a" },
129 { 90000000, 1, "a" },
130 { 91000000, 1, "a" },
131 { 92000000, 1, "a" },
132 { 93000000, 1, "a" },
133 { 94000000, 1, "a" },
134 { 95000000, 1, "a" },
135 { 96000000, 1, "a" },
136 { 97000000, 1, "a" },
137 { 98000000, 1, "a" },
138 { 99000000, 1, "a" },
139 { 99000001, 0, NULL }
140 };
141
142 static struct contents archive_contents_nonsparse[] = {
143 { 0, 1, "a" },
144 { 1, 0, NULL }
145 };
146
147 /*
148 * Describe an archive with three entries:
149 *
150 * File 1: named "sparse"
151 * * a length of 3145728 bytes (3MiB)
152 * * a single 'a' byte at offset 1000000
153 * * a single 'a' byte at offset 2000000
154 * File 2: named "sparse2"
155 * * a single 'a' byte at offset 1,000,000, 2,000,000, ..., 99,000,000
156 * * length of 99,000,001
157 * File 3: named 'non-sparse'
158 * * length of 1 byte
159 * * contains a single byte 'a'
160 */
161
162 static struct archive_contents {
163 const char *filename;
164 struct contents *contents;
165 } files[] = {
166 { "sparse", archive_contents_sparse },
167 { "sparse2", archive_contents_sparse2 },
168 { "non-sparse", archive_contents_nonsparse },
169 { NULL, NULL }
170 };
171
172 static void
verify_archive_file(const char * name,struct archive_contents * ac)173 verify_archive_file(const char *name, struct archive_contents *ac)
174 {
175 struct archive_entry *ae;
176 int err;
177 /* data, size, offset of next expected block. */
178 struct contents expect;
179 /* data, size, offset of block read from archive. */
180 struct contents actual;
181 const void *p;
182 struct archive *a;
183
184 extract_reference_file(name);
185
186 assert((a = archive_read_new()) != NULL);
187 assert(0 == archive_read_support_filter_all(a));
188 assert(0 == archive_read_support_format_tar(a));
189 failure("Can't open %s", name);
190 assert(0 == archive_read_open_filename(a, name, 3));
191
192 while (ac->filename != NULL) {
193 struct contents *cts = ac->contents;
194
195 if (!assertEqualIntA(a, 0, archive_read_next_header(a, &ae))) {
196 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
197 return;
198 }
199 failure("Name mismatch in archive %s", name);
200 assertEqualString(ac->filename, archive_entry_pathname(ae));
201 assertEqualInt(archive_entry_is_encrypted(ae), 0);
202 assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
203
204 expect = *cts++;
205 while (0 == (err = archive_read_data_block(a,
206 &p, &actual.s, &actual.o))) {
207 actual.d = p;
208 while (actual.s > 0) {
209 char c = *actual.d;
210 if(actual.o < expect.o) {
211 /*
212 * Any byte before the expected
213 * data must be NULL.
214 */
215 failure("%s: pad at offset %jd "
216 "should be zero", name,
217 (intmax_t)actual.o);
218 assertEqualInt(c, 0);
219 } else if (actual.o == expect.o) {
220 /*
221 * Data at matching offsets must match.
222 */
223 assertEqualInt(c, *expect.d);
224 expect.d++;
225 expect.o++;
226 expect.s--;
227 /* End of expected? step to next expected. */
228 if (expect.s <= 0)
229 expect = *cts++;
230 } else {
231 /*
232 * We found data beyond that expected.
233 */
234 failure("%s: Unexpected trailing data",
235 name);
236 assert(actual.o <= expect.o);
237 archive_read_free(a);
238 return;
239 }
240 actual.d++;
241 actual.o++;
242 actual.s--;
243 }
244 }
245 failure("%s: should be end of entry", name);
246 assertEqualIntA(a, err, ARCHIVE_EOF);
247 failure("%s: Size returned at EOF must be zero", name);
248 assertEqualInt((int)actual.s, 0);
249 failure("%s: Offset of final empty chunk must be same as file size", name);
250 assertEqualInt(actual.o, expect.o);
251 /* Step to next file description. */
252 ++ac;
253 }
254
255 err = archive_read_next_header(a, &ae);
256 assertEqualIntA(a, ARCHIVE_EOF, err);
257
258 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
259 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
260 }
261
262
DEFINE_TEST(test_read_format_gtar_sparse)263 DEFINE_TEST(test_read_format_gtar_sparse)
264 {
265 /* Two archives that use the "GNU tar sparse format". */
266 verify_archive_file("test_read_format_gtar_sparse_1_13.tar", files);
267 verify_archive_file("test_read_format_gtar_sparse_1_17.tar", files);
268
269 /*
270 * libarchive < 1.9 doesn't support the newer --posix sparse formats
271 * from GNU tar 1.15 and later.
272 */
273
274 /*
275 * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1
276 */
277 verify_archive_file(
278 "test_read_format_gtar_sparse_1_17_posix00.tar",
279 files);
280 /*
281 * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1
282 */
283 verify_archive_file(
284 "test_read_format_gtar_sparse_1_17_posix01.tar",
285 files);
286 /*
287 * An archive created by GNU tar 1.17 using --posix --sparse-format=1.0
288 */
289 verify_archive_file(
290 "test_read_format_gtar_sparse_1_17_posix10.tar",
291 files);
292 /*
293 * The last test archive here is a little odd. First, it's
294 * uncompressed, because that exercises some of the block
295 * reassembly code a little harder. Second, it includes some
296 * leading comments prior to the sparse block description.
297 * GNU tar doesn't do this, but I think it should, so I want
298 * to ensure that libarchive correctly ignores such comments.
299 * Dump the file, looking for "#!gnu-sparse-format" starting
300 * at byte 0x600.
301 */
302 verify_archive_file(
303 "test_read_format_gtar_sparse_1_17_posix10_modified.tar",
304 files);
305 }
306
307
308