1231200Smm/*- 2231200Smm * Copyright (c) 2009 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 27231200Smm/* 28231200Smm * Check that a "bootable CD" ISO 9660 image is correctly created. 29231200Smm */ 30231200Smm 31231200Smmstatic const unsigned char primary_id[] = { 32231200Smm 0x01, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x00 33231200Smm}; 34231200Smmstatic const unsigned char volumesize[] = { 35231200Smm 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26 36231200Smm}; 37231200Smmstatic const unsigned char volumeidu16[] = { 38231200Smm 0x00, 0x43, 0x00, 0x44, 0x00, 0x52, 0x00, 0x4f, 39231200Smm 0x00, 0x4d, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 40231200Smm 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 41231200Smm 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20 42231200Smm}; 43231200Smmstatic const unsigned char boot_id[] = { 44231200Smm 0x00, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x45, 45231200Smm 0x4c, 0x20, 0x54, 0x4f, 0x52, 0x49, 0x54, 0x4f, 46231200Smm 0x20, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 47231200Smm 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x00, 48231200Smm 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 49231200Smm}; 50231200Smm 51231200Smmstatic const unsigned char supplementary_id[] = { 52231200Smm 0x02, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x00 53231200Smm}; 54231200Smmstatic const unsigned char terminator_id[] = { 55231200Smm 0xff, 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x00 56231200Smm}; 57231200Smm 58231200Smmstatic const unsigned char boot_catalog[] = { 59231200Smm 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 60231200Smm 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 61231200Smm 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 62231200Smm 0x00, 0x00, 0x00, 0x00, 0xaa, 0x55, 0x55, 0xaa, 63231200Smm 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 64231200Smm 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 65231200Smm 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 66231200Smm 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 67231200Smm}; 68231200Smm 69231200Smmstatic const unsigned char info_table[] = { 70231200Smm 0x10, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 71231200Smm 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 72231200Smm 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 73231200Smm 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74231200Smm 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 75231200Smm 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 76231200Smm 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 77231200Smm}; 78231200Smm 79231200Smmstatic const unsigned char el_torito_signature[] = { 80231200Smm "ER\355\001\012T\207\001RRIP_1991ATHE ROCK RIDGE " 81231200Smm "INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX " 82231200Smm "FILE SYSTEM SEMANTICSPLEASE CONTACT DISC PUBLISHER " 83231200Smm "FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER " 84231200Smm "IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION." 85231200Smm}; 86231200Smm 87231200Smmchar buff2[1024]; 88231200Smm 89231200Smmstatic void 90231200Smm_test_write_format_iso9660_boot(int write_info_tbl) 91231200Smm{ 92231200Smm unsigned char nullb[2048]; 93231200Smm struct archive *a; 94231200Smm struct archive_entry *ae; 95231200Smm unsigned char *buff; 96231200Smm size_t buffsize = 39 * 2048; 97231200Smm size_t used; 98231200Smm unsigned int i; 99231200Smm 100231200Smm memset(nullb, 0, sizeof(nullb)); 101231200Smm buff = malloc(buffsize); 102231200Smm assert(buff != NULL); 103231200Smm 104231200Smm /* ISO9660 format: Create a new archive in memory. */ 105231200Smm assert((a = archive_write_new()) != NULL); 106231200Smm assertA(0 == archive_write_set_format_iso9660(a)); 107248616Smm assertA(0 == archive_write_add_filter_none(a)); 108231200Smm assertA(0 == archive_write_set_option(a, NULL, "boot", "boot.img")); 109231200Smm if (write_info_tbl) 110231200Smm assertA(0 == archive_write_set_option(a, NULL, "boot-info-table", "1")); 111231200Smm assertA(0 == archive_write_set_option(a, NULL, "pad", NULL)); 112231200Smm assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); 113231200Smm 114231200Smm /* 115231200Smm * "boot.img" has a bunch of attributes and 10K bytes of null data. 116231200Smm */ 117231200Smm assert((ae = archive_entry_new()) != NULL); 118231200Smm archive_entry_set_atime(ae, 2, 20); 119231200Smm archive_entry_set_birthtime(ae, 3, 30); 120231200Smm archive_entry_set_ctime(ae, 4, 40); 121231200Smm archive_entry_set_mtime(ae, 5, 50); 122231200Smm archive_entry_copy_pathname(ae, "boot.img"); 123231200Smm archive_entry_set_mode(ae, S_IFREG | 0755); 124231200Smm archive_entry_set_nlink(ae, 1); 125231200Smm archive_entry_set_size(ae, 10*1024); 126231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 127231200Smm archive_entry_free(ae); 128231200Smm for (i = 0; i < 10; i++) 129231200Smm assertEqualIntA(a, 1024, archive_write_data(a, nullb, 1024)); 130231200Smm 131231200Smm /* Close out the archive. */ 132231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); 133231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); 134231200Smm 135231200Smm assert(used == 2048 * 38); 136231200Smm /* Check System Area. */ 137231200Smm for (i = 0; i < 2048 * 16; i += 2048) { 138231200Smm assertEqualMem(buff+i, nullb, 2048); 139231200Smm } 140231200Smm 141231200Smm /* Primary Volume. */ 142231200Smm failure("Primary Volume Descriptor should be in 16 Logical Sector."); 143231200Smm assertEqualMem(buff+2048*16, primary_id, 8); 144231200Smm assertEqualMem(buff+2048*16+0x28, 145231200Smm "CDROM ", 32); 146231200Smm assertEqualMem(buff+2048*16+0x50, volumesize, 8); 147231200Smm 148231200Smm /* Boot Volume. */ 149231200Smm failure("Boot Volume Descriptor should be in 17 Logical Sector."); 150231200Smm assertEqualMem(buff+2048*17, boot_id, sizeof(boot_id)); 151231200Smm for (i = 0x27; i <= 0x46; i++) { 152231200Smm failure("Unused area must be all nulls."); 153231200Smm assert(buff[2048*17+i] == 0); 154231200Smm } 155231200Smm /* First sector of Boot Catalog. */ 156231200Smm assert(buff[2048*17+0x47] == 0x20); 157231200Smm assert(buff[2048*17+0x48] == 0x00); 158231200Smm assert(buff[2048*17+0x49] == 0x00); 159231200Smm assert(buff[2048*17+0x4a] == 0x00); 160231200Smm for (i = 0x4a; i <= 0x7ff; i++) { 161231200Smm failure("Unused area must be all nulls."); 162231200Smm assert(buff[2048*17+i] == 0); 163231200Smm } 164231200Smm 165231200Smm /* Supplementary Volume. */ 166231200Smm failure("Supplementary Volume(Joliet) Descriptor " 167231200Smm "should be in 18 Logical Sector."); 168231200Smm assertEqualMem(buff+2048*18, supplementary_id, 8); 169231200Smm assertEqualMem(buff+2048*18+0x28, volumeidu16, 32); 170231200Smm assertEqualMem(buff+2048*18+0x50, volumesize, 8); 171231200Smm failure("Date and Time of Primary Volume and " 172231200Smm "Date and Time of Supplementary Volume " 173231200Smm "must be the same."); 174231200Smm assertEqualMem(buff+2048*16+0x32d, buff+2048*18+0x32d, 0x44); 175231200Smm 176231200Smm /* Terminator. */ 177231200Smm failure("Volume Descriptor Set Terminator " 178231200Smm "should be in 19 Logical Sector."); 179231200Smm assertEqualMem(buff+2048*19, terminator_id, 8); 180231200Smm for (i = 8; i < 2048; i++) { 181231200Smm failure("Body of Volume Descriptor Set Terminator " 182231200Smm "should be all nulls."); 183231200Smm assert(buff[2048*19+i] == 0); 184231200Smm } 185231200Smm 186231200Smm /* Check signature of El-Torito. */ 187231200Smm assertEqualMem(buff+2048*31, el_torito_signature, 237); 188231200Smm assertEqualMem(buff+2048*31+237, nullb, 2048-237); 189231200Smm 190231200Smm /* Check contents of "boot.catalog". */ 191231200Smm assertEqualMem(buff+2048*32, boot_catalog, 64); 192231200Smm assertEqualMem(buff+2048*32+64, nullb, 2048-64); 193231200Smm 194231200Smm /* Check contents of "boot.img". */ 195231200Smm if (write_info_tbl) { 196231200Smm assertEqualMem(buff+2048*33, nullb, 8); 197231200Smm assertEqualMem(buff+2048*33+8, info_table, 56); 198231200Smm assertEqualMem(buff+2048*33+64, nullb, 2048-64); 199231200Smm } else { 200231200Smm assertEqualMem(buff+2048*33, nullb, 2048); 201231200Smm } 202231200Smm for (i = 2048*34; i < 2048*38; i += 2048) { 203231200Smm assertEqualMem(buff+i, nullb, 2048); 204231200Smm } 205231200Smm 206231200Smm /* 207231200Smm * Read ISO image. 208231200Smm */ 209231200Smm assert((a = archive_read_new()) != NULL); 210231200Smm assertEqualIntA(a, 0, archive_read_support_format_all(a)); 211231200Smm assertEqualIntA(a, 0, archive_read_support_filter_all(a)); 212231200Smm assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); 213231200Smm 214231200Smm /* 215231200Smm * Read Root Directory 216231200Smm * Root Directory entry must be in ISO image. 217231200Smm */ 218231200Smm assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); 219231200Smm assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae)); 220231200Smm assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae)); 221231200Smm assertEqualString(".", archive_entry_pathname(ae)); 222231200Smm assert((S_IFDIR | 0555) == archive_entry_mode(ae)); 223231200Smm assertEqualInt(2048, archive_entry_size(ae)); 224231200Smm 225231200Smm /* 226231200Smm * Read "boot.catalog". 227231200Smm */ 228231200Smm assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); 229231200Smm assertEqualString("boot.catalog", archive_entry_pathname(ae)); 230231200Smm#if !defined(_WIN32) && !defined(__CYGWIN__) 231231200Smm assert((S_IFREG | 0444) == archive_entry_mode(ae)); 232231200Smm#else 233231200Smm /* On Windows and CYGWIN, always set all exec bit ON by default. */ 234231200Smm assert((S_IFREG | 0555) == archive_entry_mode(ae)); 235231200Smm#endif 236231200Smm assertEqualInt(1, archive_entry_nlink(ae)); 237231200Smm assertEqualInt(2*1024, archive_entry_size(ae)); 238231200Smm assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); 239231200Smm assertEqualMem(buff2, boot_catalog, 64); 240231200Smm 241231200Smm /* 242231200Smm * Read "boot.img". 243231200Smm */ 244231200Smm assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); 245231200Smm assertEqualInt(2, archive_entry_atime(ae)); 246231200Smm assertEqualInt(3, archive_entry_birthtime(ae)); 247231200Smm assertEqualInt(4, archive_entry_ctime(ae)); 248231200Smm assertEqualInt(5, archive_entry_mtime(ae)); 249231200Smm assertEqualString("boot.img", archive_entry_pathname(ae)); 250231200Smm assert((S_IFREG | 0555) == archive_entry_mode(ae)); 251231200Smm assertEqualInt(1, archive_entry_nlink(ae)); 252231200Smm assertEqualInt(10*1024, archive_entry_size(ae)); 253231200Smm assertEqualIntA(a, 1024, archive_read_data(a, buff2, 1024)); 254231200Smm if (write_info_tbl) { 255231200Smm assertEqualMem(buff2, nullb, 8); 256231200Smm assertEqualMem(buff2+8, info_table, 56); 257231200Smm assertEqualMem(buff2+64, nullb, 1024-64); 258231200Smm } else 259231200Smm assertEqualMem(buff2, nullb, 1024); 260231200Smm 261231200Smm /* 262231200Smm * Verify the end of the archive. 263231200Smm */ 264231200Smm assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); 265231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 266231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); 267231200Smm 268231200Smm free(buff); 269231200Smm} 270231200Smm 271231200SmmDEFINE_TEST(test_write_format_iso9660_boot) 272231200Smm{ 273231200Smm _test_write_format_iso9660_boot(0); 274231200Smm /* Use 'boot-info-table' option. */ 275231200Smm _test_write_format_iso9660_boot(1); 276231200Smm} 277