]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - lib/libarchive/test/test_read_format_gtar_sparse.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / lib / libarchive / test / test_read_format_gtar_sparse.c
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 __FBSDID("$FreeBSD$");
27
28
29 struct contents {
30         off_t   o;
31         size_t  s;
32         const char *d;
33 };
34
35 struct contents archive_contents_sparse[] = {
36         { 1000000, 1, "a" },
37         { 2000000, 1, "a" },
38         { 3145728, 0, NULL }
39 };
40
41 struct contents archive_contents_sparse2[] = {
42         { 1000000, 1, "a" },
43         { 2000000, 1, "a" },
44         { 3000000, 1, "a" },
45         { 4000000, 1, "a" },
46         { 5000000, 1, "a" },
47         { 6000000, 1, "a" },
48         { 7000000, 1, "a" },
49         { 8000000, 1, "a" },
50         { 9000000, 1, "a" },
51         { 10000000, 1, "a" },
52         { 11000000, 1, "a" },
53         { 12000000, 1, "a" },
54         { 13000000, 1, "a" },
55         { 14000000, 1, "a" },
56         { 15000000, 1, "a" },
57         { 16000000, 1, "a" },
58         { 17000000, 1, "a" },
59         { 18000000, 1, "a" },
60         { 19000000, 1, "a" },
61         { 20000000, 1, "a" },
62         { 21000000, 1, "a" },
63         { 22000000, 1, "a" },
64         { 23000000, 1, "a" },
65         { 24000000, 1, "a" },
66         { 25000000, 1, "a" },
67         { 26000000, 1, "a" },
68         { 27000000, 1, "a" },
69         { 28000000, 1, "a" },
70         { 29000000, 1, "a" },
71         { 30000000, 1, "a" },
72         { 31000000, 1, "a" },
73         { 32000000, 1, "a" },
74         { 33000000, 1, "a" },
75         { 34000000, 1, "a" },
76         { 35000000, 1, "a" },
77         { 36000000, 1, "a" },
78         { 37000000, 1, "a" },
79         { 38000000, 1, "a" },
80         { 39000000, 1, "a" },
81         { 40000000, 1, "a" },
82         { 41000000, 1, "a" },
83         { 42000000, 1, "a" },
84         { 43000000, 1, "a" },
85         { 44000000, 1, "a" },
86         { 45000000, 1, "a" },
87         { 46000000, 1, "a" },
88         { 47000000, 1, "a" },
89         { 48000000, 1, "a" },
90         { 49000000, 1, "a" },
91         { 50000000, 1, "a" },
92         { 51000000, 1, "a" },
93         { 52000000, 1, "a" },
94         { 53000000, 1, "a" },
95         { 54000000, 1, "a" },
96         { 55000000, 1, "a" },
97         { 56000000, 1, "a" },
98         { 57000000, 1, "a" },
99         { 58000000, 1, "a" },
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 }
142 };
143
144 struct contents archive_contents_nonsparse[] = {
145         { 0, 1, "a" },
146         { 1, 0, NULL }
147 };
148
149 /*
150  * Describe an archive with three entries:
151  *
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'
160  *   * length of 1 byte
161  *   * contains a single byte 'a'
162  */
163
164 struct archive_contents {
165         const char *filename;
166         struct contents *contents;
167 } files[] = {
168         { "sparse", archive_contents_sparse },
169         { "sparse2", archive_contents_sparse2 },
170         { "non-sparse", archive_contents_nonsparse },
171         { NULL, NULL }
172 };
173
174 /*
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
177  * source file.
178  */
179 #define min(a,b) ((a) < (b) ? (a) : (b))
180
181 static void
182 verify_archive_file(const char *name, struct archive_contents *ac)
183 {
184         struct archive_entry *ae;
185         int err;
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;
190         struct archive *a;
191
192         extract_reference_file(name);
193
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));
199
200         while (ac->filename != NULL) {
201                 struct contents *cts = ac->contents;
202
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));
206
207                 expect = *cts++;
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) {
214                                         /*
215                                          * Any byte before the expected
216                                          * data must be NULL.
217                                          */
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) {
222                                         /*
223                                          * Data at matching offsets must match.
224                                          */
225                                         assertEqualInt(c, *expect.d);
226                                         expect.d++;
227                                         expect.o++;
228                                         expect.s--;
229                                         /* End of expected? step to next expected. */
230                                         if (expect.s <= 0)
231                                                 expect = *cts++;
232                                 } else {
233                                         /*
234                                          * We found data beyond that expected.
235                                          */
236                                         failure("%s: Unexpected trailing data",
237                                             name);
238                                         assert(actual.o <= expect.o);
239                                         archive_read_finish(a);
240                                         return;
241                                 }
242                                 actual.d++;
243                                 actual.o++;
244                                 actual.s--;
245                         }
246                 }
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_STAMP < 1009000
252                 /* libarchive < 1.9 doesn't get this right */
253                 skipping("offset of final sparse chunk");
254 #else
255                 failure("%s: Offset of final empty chunk must be same as file size", name);
256                 assertEqualInt(actual.o, expect.o);
257 #endif
258                 /* Step to next file description. */
259                 ++ac;
260         }
261
262         err = archive_read_next_header(a, &ae);
263         assertEqualIntA(a, ARCHIVE_EOF, err);
264
265         assert(0 == archive_read_close(a));
266 #if ARCHIVE_API_VERSION > 1
267         assert(0 == archive_read_finish(a));
268 #else
269         archive_read_finish(a);
270 #endif
271 }
272
273
274 DEFINE_TEST(test_read_format_gtar_sparse)
275 {
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);
279
280         /*
281          * libarchive < 1.9 doesn't support the newer --posix sparse formats
282          * from GNU tar 1.15 and later.
283          */
284 #if ARCHIVE_VERSION_STAMP < 1009000
285         skipping("read support for GNUtar --posix sparse formats");
286 #else
287         /*
288          * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1
289          */
290         verify_archive_file(
291                 "test_read_format_gtar_sparse_1_17_posix00.tgz",
292                 files);
293         /*
294          * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1
295          */
296         verify_archive_file(
297                 "test_read_format_gtar_sparse_1_17_posix01.tgz",
298                 files);
299         /*
300          * An archive created by GNU tar 1.17 using --posix --sparse-format=1.0
301          */
302         verify_archive_file(
303                 "test_read_format_gtar_sparse_1_17_posix10.tgz",
304                 files);
305         /*
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
313          * at byte 0x600.
314          */
315         verify_archive_file(
316                 "test_read_format_gtar_sparse_1_17_posix10_modified.tar",
317                 files);
318 #endif
319 }
320
321