1231200Smm/*- 2231200Smm * Copyright (c) 2010 Michihiro NAKAJIMA 3231200Smm * All rights reserved. 4231200Smm * 5231200Smm * Redistribution and use in source and binary forms, with or without 6231200Smm * modification, are permitted provided that the following conditions 7231200Smm * are met: 8231200Smm * 1. Redistributions of source code must retain the above copyright 9231200Smm * notice, this list of conditions and the following disclaimer. 10231200Smm * 2. Redistributions in binary form must reproduce the above copyright 11231200Smm * notice, this list of conditions and the following disclaimer in the 12231200Smm * documentation and/or other materials provided with the distribution. 13231200Smm * 14231200Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15231200Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16231200Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17231200Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18231200Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19231200Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20231200Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21231200Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22231200Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23231200Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24231200Smm */ 25231200Smm#include "test.h" 26231200Smm__FBSDID("$FreeBSD"); 27231200Smm 28231200Smm#ifdef HAVE_LIBZ 29231200Smmstatic const int libz_enabled = 1; 30231200Smm#else 31231200Smmstatic const int libz_enabled = 0; 32231200Smm#endif 33231200Smm 34231200Smm/* 35231200SmmExecute the following command to rebuild the data for this program: 36231200Smm tail -n +44 test_read_format_cab.c | /bin/sh 37231200SmmAnd following works are: 38231200Smm1. Move /tmp/cab/cab.zip to Windows PC 39231200Smm2. Extract cab.zip 40231200Smm3. Open command prompt and change current directory where you extracted cab.zip 41231200Smm4. Execute cab.bat 42231200Smm5. Then you will see that there is a cabinet file, test.cab 43231200Smm6. Move test.cab to posix platform 44231200Smm7. Extract test.cab with this version of bsdtar 45231200Smm8. Execute the following command to make uuencoded files. 46231200Smm uuencode test_read_format_cab_1.cab test_read_format_cab_1.cab > test_read_format_cab_1.cab.uu 47231200Smm uuencode test_read_format_cab_2.cab test_read_format_cab_2.cab > test_read_format_cab_2.cab.uu 48231200Smm uuencode test_read_format_cab_3.cab test_read_format_cab_3.cab > test_read_format_cab_3.cab.uu 49231200Smm 50231200Smm#!/bin/sh 51231200Smm# 52231200Smm# How to make test data. 53231200Smm# 54231200Smm# Temporary directory. 55231200Smmbase=/tmp/cab 56231200Smm# Owner id 57231200Smmowner=1001 58231200Smm# Group id 59231200Smmgroup=1001 60231200Smm# 61231200Smm# Make contents of a cabinet file. 62231200Smm# 63231200Smmrm -rf ${base} 64231200Smmmkdir ${base} 65231200Smmmkdir ${base}/dir1 66231200Smmmkdir ${base}/dir2 67231200Smm# 68231200Smmtouch ${base}/empty 69231200Smmcat > ${base}/dir1/file1 << END 70231200Smm file 1 contents 71231200Smmhello 72231200Smmhello 73231200Smmhello 74231200SmmEND 75231200Smm# 76231200Smmcat > ${base}/dir2/file2 << END 77231200Smm file 2 contents 78231200Smmhello 79231200Smmhello 80231200Smmhello 81231200Smmhello 82231200Smmhello 83231200Smmhello 84231200SmmEND 85231200Smm# 86231200Smmdd if=/dev/zero of=${base}/zero bs=1 count=33000 > /dev/null 2>&1 87231200Smm# 88231200Smmcab1=test_read_format_cab_1.cab 89231200Smmcab2=test_read_format_cab_2.cab 90231200Smmcab3=test_read_format_cab_3.cab 91231200Smm# 92231200Smm# 93231200Smmcat > ${base}/mkcab1 << END 94231200Smm.Set Compress=OFF 95231200Smm.Set DiskDirectory1=. 96231200Smm.Set InfDate=1980-01-02 97231200Smm.Set InfTime=00:00:00 98231200Smm.Set CabinetName1=${cab1} 99231200Smmempty 100231200Smm.Set DestinationDir=dir1 101231200Smmdir1/file1 102231200Smm.Set DestinationDir=dir2 103231200Smmdir2/file2 104231200SmmEND 105231200Smm# 106231200Smmcat > ${base}/mkcab2 << END 107231200Smm.Set CompressionType=MSZIP 108231200Smm.Set DiskDirectory1=. 109231200Smm.Set InfDate=1980-01-02 110231200Smm.Set InfTime=00:00:00 111231200Smm.Set CabinetName1=${cab2} 112231200Smmempty 113231200Smmzero 114231200Smm.Set DestinationDir=dir1 115231200Smmdir1/file1 116231200Smm.Set DestinationDir=dir2 117231200Smmdir2/file2 118231200SmmEND 119231200Smm# 120231200Smmcat > ${base}/mkcab3 << END 121231200Smm.Set CompressionType=LZX 122231200Smm.Set DiskDirectory1=. 123231200Smm.Set InfDate=1980-01-02 124231200Smm.Set InfTime=00:00:00 125231200Smm.Set CabinetName1=${cab3} 126231200Smmempty 127231200Smmzero 128231200Smm.Set DestinationDir=dir1 129231200Smmdir1/file1 130231200Smm.Set DestinationDir=dir2 131231200Smmdir2/file2 132231200SmmEND 133231200Smm# 134231200Smmcat > ${base}/mkcab4 << END 135231200Smm.Set CompressionType=MSZIP 136231200Smm.Set DiskDirectory1=. 137231200Smm.Set CabinetName1=test.cab 138231200Smm${cab1} 139231200Smm${cab2} 140231200Smm${cab3} 141231200SmmEND 142231200Smm# 143231200Smmcat > ${base}/cab.bat << END 144231200Smmmakecab.exe /F mkcab1 145231200Smmmakecab.exe /F mkcab2 146231200Smmmakecab.exe /F mkcab3 147231200Smmmakecab.exe /F mkcab4 148231200Smmdel setup.inf setup.rpt 149231200Smmdel empty zero dir1\file1 dir2\file2 mkcab1 mkcab2 mkcab3 mkcab4 150231200Smmdel ${cab1} ${cab2} ${cab3} 151231200Smmrmdir dir1 dir2 152231200SmmEND 153231200Smm# 154231200Smmf=cab.zip 155231200Smm(cd ${base}; zip -q -c $f empty zero dir1/file1 dir2/file2 mkcab1 mkcab2 mkcab3 mkcab4 cab.bat) 156231200Smm# 157231200Smmexit 1 158231200Smm*/ 159231200Smm 160231200Smmstatic const char file1[] = { 161231200Smm" file 1 contents\n" 162231200Smm"hello\n" 163231200Smm"hello\n" 164231200Smm"hello\n" 165231200Smm}; 166231200Smm#define file1_size (sizeof(file1)-1) 167231200Smmstatic const char file2[] = { 168231200Smm" file 2 contents\n" 169231200Smm"hello\n" 170231200Smm"hello\n" 171231200Smm"hello\n" 172231200Smm"hello\n" 173231200Smm"hello\n" 174231200Smm"hello\n" 175231200Smm}; 176231200Smm#define file2_size (sizeof(file2)-1) 177231200Smm 178231200Smmenum comp_type { 179231200Smm STORE = 0, 180231200Smm MSZIP, 181231200Smm LZX 182231200Smm}; 183231200Smmstatic void 184231200Smmverify(const char *refname, enum comp_type comp) 185231200Smm{ 186231200Smm struct archive_entry *ae; 187231200Smm struct archive *a; 188231200Smm char buff[128]; 189231200Smm char zero[128]; 190231200Smm size_t s; 191231200Smm 192231200Smm memset(zero, 0, sizeof(zero)); 193231200Smm extract_reference_file(refname); 194231200Smm assert((a = archive_read_new()) != NULL); 195231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 196231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 197231200Smm assertEqualIntA(a, ARCHIVE_OK, 198231200Smm archive_read_open_filename(a, refname, 10240)); 199231200Smm 200231200Smm /* Verify regular empty. */ 201231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 202238856Smm assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae)); 203231200Smm assertEqualString("empty", archive_entry_pathname(ae)); 204231200Smm assertEqualInt(0, archive_entry_uid(ae)); 205231200Smm assertEqualInt(0, archive_entry_gid(ae)); 206231200Smm assertEqualInt(0, archive_entry_size(ae)); 207231200Smm 208231200Smm if (comp != STORE) { 209231200Smm /* Verify regular zero. 210231200Smm * Maximum CFDATA size is 32768, so we need over 32768 bytes 211231200Smm * file to check if we properly handle multiple CFDATA. 212231200Smm */ 213231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 214238856Smm assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae)); 215231200Smm assertEqualString("zero", archive_entry_pathname(ae)); 216231200Smm assertEqualInt(0, archive_entry_uid(ae)); 217231200Smm assertEqualInt(0, archive_entry_gid(ae)); 218231200Smm assertEqualInt(33000, archive_entry_size(ae)); 219231200Smm for (s = 0; s + sizeof(buff) < 33000; s+= sizeof(buff)) { 220231200Smm ssize_t rsize = archive_read_data(a, buff, sizeof(buff)); 221231200Smm if (comp == MSZIP && rsize == ARCHIVE_FATAL && !libz_enabled) { 222231200Smm skipping("Skipping CAB format(MSZIP) check: %s", 223231200Smm archive_error_string(a)); 224231200Smm goto finish; 225231200Smm } 226231200Smm assertEqualInt(sizeof(buff), rsize); 227231200Smm assertEqualMem(buff, zero, sizeof(buff)); 228231200Smm } 229231200Smm assertEqualInt(33000 - s, archive_read_data(a, buff, 33000 - s)); 230231200Smm assertEqualMem(buff, zero, 33000 - s); 231231200Smm } 232231200Smm 233231200Smm /* Verify regular file1. */ 234231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 235238856Smm assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae)); 236231200Smm assertEqualString("dir1/file1", archive_entry_pathname(ae)); 237231200Smm assertEqualInt(0, archive_entry_uid(ae)); 238231200Smm assertEqualInt(0, archive_entry_gid(ae)); 239231200Smm assertEqualInt(file1_size, archive_entry_size(ae)); 240231200Smm assertEqualInt(file1_size, archive_read_data(a, buff, file1_size)); 241231200Smm assertEqualMem(buff, file1, file1_size); 242231200Smm 243231200Smm /* Verify regular file2. */ 244231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 245238856Smm assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae)); 246231200Smm assertEqualString("dir2/file2", archive_entry_pathname(ae)); 247231200Smm assertEqualInt(0, archive_entry_uid(ae)); 248231200Smm assertEqualInt(0, archive_entry_gid(ae)); 249231200Smm assertEqualInt(file2_size, archive_entry_size(ae)); 250231200Smm assertEqualInt(file2_size, archive_read_data(a, buff, file2_size)); 251231200Smm assertEqualMem(buff, file2, file2_size); 252231200Smm 253231200Smm /* End of archive. */ 254231200Smm assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); 255231200Smm 256231200Smm if (comp != STORE) { 257231200Smm assertEqualInt(4, archive_file_count(a)); 258231200Smm } else { 259231200Smm assertEqualInt(3, archive_file_count(a)); 260231200Smm } 261231200Smm 262231200Smm /* Verify archive format. */ 263248616Smm assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); 264231200Smm assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a)); 265231200Smm 266231200Smm /* Close the archive. */ 267231200Smmfinish: 268231200Smm assertEqualInt(ARCHIVE_OK, archive_read_close(a)); 269231200Smm assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 270231200Smm} 271231200Smm 272238856Smm/* 273238856Smm * Skip beginning files and Read the last file. 274238856Smm */ 275238856Smmstatic void 276238856Smmverify2(const char *refname, enum comp_type comp) 277238856Smm{ 278238856Smm struct archive_entry *ae; 279238856Smm struct archive *a; 280238856Smm char buff[128]; 281238856Smm char zero[128]; 282238856Smm 283248616Smm if (comp == MSZIP && !libz_enabled) { 284248616Smm skipping("Skipping CAB format(MSZIP) check for %s", 285248616Smm refname); 286248616Smm return; 287248616Smm } 288238856Smm memset(zero, 0, sizeof(zero)); 289238856Smm extract_reference_file(refname); 290238856Smm assert((a = archive_read_new()) != NULL); 291238856Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 292238856Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 293238856Smm assertEqualIntA(a, ARCHIVE_OK, 294238856Smm archive_read_open_filename(a, refname, 10240)); 295238856Smm 296238856Smm /* Verify regular empty. */ 297238856Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 298238856Smm if (comp != STORE) { 299238856Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 300238856Smm } 301238856Smm /* Verify regular file1. */ 302238856Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 303238856Smm 304238856Smm /* Verify regular file2. */ 305238856Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 306238856Smm assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae)); 307238856Smm assertEqualString("dir2/file2", archive_entry_pathname(ae)); 308238856Smm assertEqualInt(0, archive_entry_uid(ae)); 309238856Smm assertEqualInt(0, archive_entry_gid(ae)); 310238856Smm assertEqualInt(file2_size, archive_entry_size(ae)); 311238856Smm assertEqualInt(file2_size, archive_read_data(a, buff, file2_size)); 312238856Smm assertEqualMem(buff, file2, file2_size); 313238856Smm 314238856Smm /* End of archive. */ 315238856Smm assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); 316238856Smm 317238856Smm if (comp != STORE) { 318238856Smm assertEqualInt(4, archive_file_count(a)); 319238856Smm } else { 320238856Smm assertEqualInt(3, archive_file_count(a)); 321238856Smm } 322238856Smm 323238856Smm /* Verify archive format. */ 324248616Smm assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); 325238856Smm assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a)); 326238856Smm 327238856Smm /* Close the archive. */ 328238856Smm assertEqualInt(ARCHIVE_OK, archive_read_close(a)); 329238856Smm assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 330238856Smm} 331238856Smm 332238856Smm/* 333238856Smm * Skip all file like 'bsdtar tvf foo.cab'. 334238856Smm */ 335238856Smmstatic void 336238856Smmverify3(const char *refname, enum comp_type comp) 337238856Smm{ 338238856Smm struct archive_entry *ae; 339238856Smm struct archive *a; 340238856Smm char zero[128]; 341238856Smm 342238856Smm memset(zero, 0, sizeof(zero)); 343238856Smm extract_reference_file(refname); 344238856Smm assert((a = archive_read_new()) != NULL); 345238856Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 346238856Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 347238856Smm assertEqualIntA(a, ARCHIVE_OK, 348238856Smm archive_read_open_filename(a, refname, 10240)); 349238856Smm 350238856Smm /* Verify regular empty. */ 351238856Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 352238856Smm if (comp != STORE) { 353238856Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 354238856Smm } 355238856Smm /* Verify regular file1. */ 356238856Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 357238856Smm 358238856Smm /* Verify regular file2. */ 359238856Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 360238856Smm 361238856Smm /* End of archive. */ 362238856Smm assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); 363238856Smm 364238856Smm if (comp != STORE) { 365238856Smm assertEqualInt(4, archive_file_count(a)); 366238856Smm } else { 367238856Smm assertEqualInt(3, archive_file_count(a)); 368238856Smm } 369238856Smm 370238856Smm /* Verify archive format. */ 371248616Smm assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); 372238856Smm assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a)); 373238856Smm 374238856Smm /* Close the archive. */ 375238856Smm assertEqualInt(ARCHIVE_OK, archive_read_close(a)); 376238856Smm assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 377238856Smm} 378238856Smm 379231200SmmDEFINE_TEST(test_read_format_cab) 380231200Smm{ 381231200Smm /* Verify Cabinet file in no compression. */ 382231200Smm verify("test_read_format_cab_1.cab", STORE); 383238856Smm verify2("test_read_format_cab_1.cab", STORE); 384238856Smm verify3("test_read_format_cab_1.cab", STORE); 385231200Smm /* Verify Cabinet file in MSZIP. */ 386231200Smm verify("test_read_format_cab_2.cab", MSZIP); 387238856Smm verify2("test_read_format_cab_2.cab", MSZIP); 388238856Smm verify3("test_read_format_cab_2.cab", MSZIP); 389231200Smm /* Verify Cabinet file in LZX. */ 390231200Smm verify("test_read_format_cab_3.cab", LZX); 391238856Smm verify2("test_read_format_cab_3.cab", LZX); 392238856Smm verify3("test_read_format_cab_3.cab", LZX); 393231200Smm} 394231200Smm 395