test_read_format_gtar_sparse.c revision 228753
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: head/lib/libarchive/test/test_read_format_gtar_sparse.c 189308 2009-03-03 17:02:51Z kientzle $"); 27 28 29struct contents { 30 off_t o; 31 size_t s; 32 const char *d; 33}; 34 35struct contents archive_contents_sparse[] = { 36 { 1000000, 1, "a" }, 37 { 2000000, 1, "a" }, 38 { 3145728, 0, NULL } 39}; 40 41struct 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 144struct 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 164struct 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 174static void 175verify_archive_file(const char *name, struct archive_contents *ac) 176{ 177 struct archive_entry *ae; 178 int err; 179 /* data, size, offset of next expected block. */ 180 struct contents expect; 181 /* data, size, offset of block read from archive. */ 182 struct contents actual; 183 const void *p; 184 struct archive *a; 185 186 extract_reference_file(name); 187 188 assert((a = archive_read_new()) != NULL); 189 assert(0 == archive_read_support_compression_all(a)); 190 assert(0 == archive_read_support_format_tar(a)); 191 failure("Can't open %s", name); 192 assert(0 == archive_read_open_filename(a, name, 3)); 193 194 while (ac->filename != NULL) { 195 struct contents *cts = ac->contents; 196 197 if (!assertEqualIntA(a, 0, archive_read_next_header(a, &ae))) { 198 assert(0 == archive_read_finish(a)); 199 return; 200 } 201 failure("Name mismatch in archive %s", name); 202 assertEqualString(ac->filename, archive_entry_pathname(ae)); 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 %d " 216 "should be zero", name, actual.o); 217 assertEqualInt(c, 0); 218 } else if (actual.o == expect.o) { 219 /* 220 * Data at matching offsets must match. 221 */ 222 assertEqualInt(c, *expect.d); 223 expect.d++; 224 expect.o++; 225 expect.s--; 226 /* End of expected? step to next expected. */ 227 if (expect.s <= 0) 228 expect = *cts++; 229 } else { 230 /* 231 * We found data beyond that expected. 232 */ 233 failure("%s: Unexpected trailing data", 234 name); 235 assert(actual.o <= expect.o); 236 archive_read_finish(a); 237 return; 238 } 239 actual.d++; 240 actual.o++; 241 actual.s--; 242 } 243 } 244 failure("%s: should be end of entry", name); 245 assertEqualIntA(a, err, ARCHIVE_EOF); 246 failure("%s: Size returned at EOF must be zero", name); 247 assertEqualInt((int)actual.s, 0); 248#if ARCHIVE_VERSION_NUMBER < 1009000 249 /* libarchive < 1.9 doesn't get this right */ 250 skipping("offset of final sparse chunk"); 251#else 252 failure("%s: Offset of final empty chunk must be same as file size", name); 253 assertEqualInt(actual.o, expect.o); 254#endif 255 /* Step to next file description. */ 256 ++ac; 257 } 258 259 err = archive_read_next_header(a, &ae); 260 assertEqualIntA(a, ARCHIVE_EOF, err); 261 262 assert(0 == archive_read_close(a)); 263#if ARCHIVE_VERSION_NUMBER < 2000000 264 archive_read_finish(a); 265#else 266 assert(0 == archive_read_finish(a)); 267#endif 268} 269 270 271DEFINE_TEST(test_read_format_gtar_sparse) 272{ 273 /* Two archives that use the "GNU tar sparse format". */ 274 verify_archive_file("test_read_format_gtar_sparse_1_13.tar", files); 275 verify_archive_file("test_read_format_gtar_sparse_1_17.tar", files); 276 277 /* 278 * libarchive < 1.9 doesn't support the newer --posix sparse formats 279 * from GNU tar 1.15 and later. 280 */ 281#if ARCHIVE_VERSION_NUMBER < 1009000 282 skipping("read support for GNUtar --posix sparse formats"); 283#else 284 /* 285 * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1 286 */ 287 verify_archive_file( 288 "test_read_format_gtar_sparse_1_17_posix00.tar", 289 files); 290 /* 291 * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1 292 */ 293 verify_archive_file( 294 "test_read_format_gtar_sparse_1_17_posix01.tar", 295 files); 296 /* 297 * An archive created by GNU tar 1.17 using --posix --sparse-format=1.0 298 */ 299 verify_archive_file( 300 "test_read_format_gtar_sparse_1_17_posix10.tar", 301 files); 302 /* 303 * The last test archive here is a little odd. First, it's 304 * uncompressed, because that exercises some of the block 305 * reassembly code a little harder. Second, it includes some 306 * leading comments prior to the sparse block description. 307 * GNU tar doesn't do this, but I think it should, so I want 308 * to ensure that libarchive correctly ignores such comments. 309 * Dump the file, looking for "#!gnu-sparse-format" starting 310 * at byte 0x600. 311 */ 312 verify_archive_file( 313 "test_read_format_gtar_sparse_1_17_posix10_modified.tar", 314 files); 315#endif 316} 317 318 319