test_write_format_iso9660_filename.c revision 248616
1231200Smm/*- 2231200Smm * Copyright (c) 2009,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 27231200Smm/* 28231200Smm * Check that an ISO 9660 image is correctly created. 29231200Smm */ 30231200Smmstatic void 31231200Smmadd_entry(struct archive *a, const char *fname, const char *sym) 32231200Smm{ 33231200Smm struct archive_entry *ae; 34231200Smm 35231200Smm assert((ae = archive_entry_new()) != NULL); 36231200Smm archive_entry_set_birthtime(ae, 2, 20); 37231200Smm archive_entry_set_atime(ae, 3, 30); 38231200Smm archive_entry_set_ctime(ae, 4, 40); 39231200Smm archive_entry_set_mtime(ae, 5, 50); 40231200Smm archive_entry_copy_pathname(ae, fname); 41231200Smm if (sym != NULL) 42231200Smm archive_entry_set_symlink(ae, sym); 43231200Smm archive_entry_set_mode(ae, S_IFREG | 0555); 44231200Smm archive_entry_set_size(ae, 0); 45231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 46231200Smm archive_entry_free(ae); 47231200Smm} 48231200Smm 49231200Smmstruct fns { 50231200Smm size_t maxlen; 51231200Smm size_t longest_len; 52231200Smm size_t maxflen; 53231200Smm size_t maxelen; 54231200Smm size_t alloc; 55231200Smm int cnt; 56231200Smm char **names; 57231200Smm int opt; 58231200Smm#define UPPER_CASE_ONLY 0x00001 59231200Smm#define ONE_DOT 0x00002 60231200Smm#define ALLOW_LDOT 0x00004 61231200Smm}; 62231200Smm 63231200Smmenum vtype { 64231200Smm ROCKRIDGE, 65231200Smm JOLIET, 66231200Smm ISO9660 67231200Smm}; 68231200Smm 69231200Smm/* 70231200Smm * Verify file 71231200Smm */ 72231200Smmstatic void 73231200Smmverify_file(struct archive *a, enum vtype type, struct fns *fns) 74231200Smm{ 75231200Smm struct archive_entry *ae; 76231200Smm int i; 77231200Smm 78231200Smm assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); 79231200Smm if (type == ROCKRIDGE) { 80231200Smm assertEqualInt(2, archive_entry_birthtime(ae)); 81231200Smm assertEqualInt(3, archive_entry_atime(ae)); 82231200Smm assertEqualInt(4, archive_entry_ctime(ae)); 83231200Smm } else { 84231200Smm assertEqualInt(0, archive_entry_birthtime_is_set(ae)); 85231200Smm assertEqualInt(5, archive_entry_atime(ae)); 86231200Smm assertEqualInt(5, archive_entry_ctime(ae)); 87231200Smm } 88231200Smm assertEqualInt(5, archive_entry_mtime(ae)); 89231200Smm if (type == ROCKRIDGE) 90231200Smm assert((S_IFREG | 0555) == archive_entry_mode(ae)); 91231200Smm else 92231200Smm assert((S_IFREG | 0400) == archive_entry_mode(ae)); 93231200Smm assertEqualInt(0, archive_entry_size(ae)); 94231200Smm 95231200Smm /* 96231200Smm * Check if the same filename does not appear. 97231200Smm */ 98231200Smm for (i = 0; i < fns->cnt; i++) { 99231200Smm const char *p; 100231200Smm const char *pathname = archive_entry_pathname(ae); 101232153Smm const char *symlinkname = archive_entry_symlink(ae); 102231200Smm size_t length; 103231200Smm 104232153Smm if (symlinkname != NULL) { 105232153Smm length = strlen(symlinkname); 106231200Smm assert(length == 1 || length == 128 || length == 255); 107232153Smm assertEqualInt(symlinkname[length-1], 'x'); 108231200Smm } 109231200Smm failure("Found duplicate for %s", pathname); 110231200Smm assert(strcmp(fns->names[i], pathname) != 0); 111231200Smm assert((length = strlen(pathname)) <= fns->maxlen); 112231200Smm if (length > fns->longest_len) 113231200Smm fns->longest_len = length; 114231200Smm p = strrchr(pathname, '.'); 115231200Smm if (p != NULL) { 116231200Smm /* Check a length of file name. */ 117231200Smm assert((size_t)(p - pathname) <= fns->maxflen); 118231200Smm /* Check a length of file extension. */ 119231200Smm assert(strlen(p+1) <= fns->maxelen); 120231200Smm if (fns->opt & ONE_DOT) { 121231200Smm /* Do not have multi dot. */ 122231200Smm assert(strchr(pathname, '.') == p); 123231200Smm } 124231200Smm } 125231200Smm for (p = pathname; *p; p++) { 126231200Smm if (fns->opt & UPPER_CASE_ONLY) { 127231200Smm /* Do not have any lower-case character. */ 128231200Smm assert(*p < 'a' || *p > 'z'); 129231200Smm } else 130231200Smm break; 131231200Smm } 132231200Smm if ((fns->opt & ALLOW_LDOT) == 0) 133231200Smm /* Do not have a dot at the first position. */ 134231200Smm assert(*pathname != '.'); 135231200Smm } 136231200Smm /* Save the filename which is appeared to use above next time. */ 137231200Smm fns->names[fns->cnt++] = strdup(archive_entry_pathname(ae)); 138231200Smm} 139231200Smm 140231200Smmstatic void 141231200Smmverify(unsigned char *buff, size_t used, enum vtype type, struct fns *fns) 142231200Smm{ 143231200Smm struct archive *a; 144231200Smm struct archive_entry *ae; 145231200Smm size_t i; 146231200Smm 147231200Smm /* 148231200Smm * Read ISO image. 149231200Smm */ 150231200Smm assert((a = archive_read_new()) != NULL); 151231200Smm assertEqualIntA(a, 0, archive_read_support_format_all(a)); 152231200Smm assertEqualIntA(a, 0, archive_read_support_filter_all(a)); 153231200Smm if (type >= 1) 154231200Smm assertA(0 == archive_read_set_option(a, NULL, "rockridge", 155231200Smm NULL)); 156231200Smm if (type >= 2) 157231200Smm assertA(0 == archive_read_set_option(a, NULL, "joliet", 158231200Smm NULL)); 159231200Smm assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); 160231200Smm 161231200Smm /* 162231200Smm * Read Root Directory 163231200Smm * Root Directory entry must be in ISO image. 164231200Smm */ 165231200Smm assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); 166231200Smm assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae)); 167231200Smm assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae)); 168231200Smm assertEqualString(".", archive_entry_pathname(ae)); 169231200Smm switch (type) { 170231200Smm case ROCKRIDGE: 171231200Smm assert((S_IFDIR | 0555) == archive_entry_mode(ae)); 172231200Smm break; 173231200Smm case JOLIET: 174231200Smm assert((S_IFDIR | 0700) == archive_entry_mode(ae)); 175231200Smm break; 176231200Smm case ISO9660: 177231200Smm assert((S_IFDIR | 0700) == archive_entry_mode(ae)); 178231200Smm break; 179231200Smm } 180231200Smm 181231200Smm /* 182231200Smm * Verify file status. 183231200Smm */ 184231200Smm memset(fns->names, 0, sizeof(char *) * fns->alloc); 185231200Smm fns->cnt = 0; 186231200Smm for (i = 0; i < fns->alloc; i++) 187231200Smm verify_file(a, type, fns); 188231200Smm for (i = 0; i < fns->alloc; i++) 189231200Smm free(fns->names[i]); 190231200Smm assertEqualInt((int)fns->longest_len, (int)fns->maxlen); 191231200Smm 192231200Smm /* 193231200Smm * Verify the end of the archive. 194231200Smm */ 195231200Smm assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); 196231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 197231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); 198231200Smm} 199231200Smm 200231200Smmstatic int 201231200Smmcreate_iso_image(unsigned char *buff, size_t buffsize, size_t *used, 202231200Smm const char *opt) 203231200Smm{ 204231200Smm struct archive *a; 205231200Smm int i, l, fcnt; 206231200Smm const int lens[] = { 207231200Smm 0, 1, 3, 5, 7, 8, 9, 29, 30, 31, 32, 208231200Smm 62, 63, 64, 65, 101, 102, 103, 104, 209231200Smm 191, 192, 193, 194, 204, 205, 206, 207, 208, 210231200Smm 252, 253, 254, 255, 211231200Smm -1 }; 212231200Smm char fname1[256]; 213231200Smm char fname2[256]; 214231200Smm char sym1[2]; 215231200Smm char sym128[129]; 216231200Smm char sym255[256]; 217231200Smm 218231200Smm /* ISO9660 format: Create a new archive in memory. */ 219231200Smm assert((a = archive_write_new()) != NULL); 220231200Smm assertA(0 == archive_write_set_format_iso9660(a)); 221248616Smm assertA(0 == archive_write_add_filter_none(a)); 222231200Smm assertA(0 == archive_write_set_option(a, NULL, "pad", NULL)); 223231200Smm if (opt) 224231200Smm assertA(0 == archive_write_set_options(a, opt)); 225231200Smm assertA(0 == archive_write_set_bytes_per_block(a, 1)); 226231200Smm assertA(0 == archive_write_set_bytes_in_last_block(a, 1)); 227231200Smm assertA(0 == archive_write_open_memory(a, buff, buffsize, used)); 228231200Smm 229231200Smm sym1[0] = 'x'; 230231200Smm sym1[1] = '\0'; 231232153Smm for (i = 0; i < (int)sizeof(sym128)-2; i++) 232231200Smm sym128[i] = 'a'; 233231200Smm sym128[sizeof(sym128)-2] = 'x'; 234231200Smm sym128[sizeof(sym128)-1] = '\0'; 235232153Smm for (i = 0; i < (int)sizeof(sym255)-2; i++) 236231200Smm sym255[i] = 'a'; 237231200Smm sym255[sizeof(sym255)-2] = 'x'; 238231200Smm sym255[sizeof(sym255)-1] = '\0'; 239231200Smm 240231200Smm fcnt = 0; 241231200Smm for (i = 0; lens[i] >= 0; i++) { 242231200Smm for (l = 0; l < lens[i]; l++) { 243231200Smm fname1[l] = 'a'; 244231200Smm fname2[l] = 'A'; 245231200Smm } 246231200Smm if (l > 0) { 247231200Smm fname1[l] = '\0'; 248231200Smm fname2[l] = '\0'; 249231200Smm add_entry(a, fname1, NULL); 250231200Smm add_entry(a, fname2, sym1); 251231200Smm fcnt += 2; 252231200Smm } 253231200Smm if (l < 254) { 254231200Smm fname1[l] = '.'; 255231200Smm fname1[l+1] = 'c'; 256231200Smm fname1[l+2] = '\0'; 257231200Smm fname2[l] = '.'; 258231200Smm fname2[l+1] = 'C'; 259231200Smm fname2[l+2] = '\0'; 260231200Smm add_entry(a, fname1, sym128); 261231200Smm add_entry(a, fname2, sym255); 262231200Smm fcnt += 2; 263231200Smm } 264231200Smm if (l < 252) { 265231200Smm fname1[l] = '.'; 266231200Smm fname1[l+1] = 'p'; 267231200Smm fname1[l+2] = 'n'; 268231200Smm fname1[l+3] = 'g'; 269231200Smm fname1[l+4] = '\0'; 270231200Smm fname2[l] = '.'; 271231200Smm fname2[l+1] = 'P'; 272231200Smm fname2[l+2] = 'N'; 273231200Smm fname2[l+3] = 'G'; 274231200Smm fname2[l+4] = '\0'; 275231200Smm add_entry(a, fname1, NULL); 276231200Smm add_entry(a, fname2, sym1); 277231200Smm fcnt += 2; 278231200Smm } 279231200Smm if (l < 251) { 280231200Smm fname1[l] = '.'; 281231200Smm fname1[l+1] = 'j'; 282231200Smm fname1[l+2] = 'p'; 283231200Smm fname1[l+3] = 'e'; 284231200Smm fname1[l+4] = 'g'; 285231200Smm fname1[l+5] = '\0'; 286231200Smm fname2[l] = '.'; 287231200Smm fname2[l+1] = 'J'; 288231200Smm fname2[l+2] = 'P'; 289231200Smm fname2[l+3] = 'E'; 290231200Smm fname2[l+4] = 'G'; 291231200Smm fname2[l+5] = '\0'; 292231200Smm add_entry(a, fname1, sym128); 293231200Smm add_entry(a, fname2, sym255); 294231200Smm fcnt += 2; 295231200Smm } 296231200Smm } 297231200Smm 298231200Smm /* Close out the archive. */ 299231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); 300231200Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); 301231200Smm 302231200Smm return (fcnt); 303231200Smm} 304231200Smm 305231200SmmDEFINE_TEST(test_write_format_iso9660_filename) 306231200Smm{ 307231200Smm unsigned char *buff; 308231200Smm size_t buffsize = 120 * 2048; 309231200Smm size_t used; 310231200Smm int fcnt; 311231200Smm struct fns fns; 312231200Smm 313231200Smm buff = malloc(buffsize); 314231200Smm assert(buff != NULL); 315248616Smm if (buff == NULL) 316248616Smm return; 317231200Smm memset(&fns, 0, sizeof(fns)); 318231200Smm 319231200Smm /* 320231200Smm * Create ISO image with no option. 321231200Smm */ 322231200Smm fcnt = create_iso_image(buff, buffsize, &used, NULL); 323231200Smm 324231200Smm fns.names = (char **)malloc(sizeof(char *) * fcnt); 325231200Smm assert(fns.names != NULL); 326248616Smm if (fns.names == NULL) { 327248616Smm free(buff); 328248616Smm return; 329248616Smm } 330231200Smm fns.alloc = fcnt; 331231200Smm 332231200Smm /* Verify rockridge filenames. */ 333231200Smm fns.longest_len = 0; 334231200Smm fns.maxlen = fns.maxflen = fns.maxelen = 255; 335231200Smm fns.opt = ALLOW_LDOT; 336231200Smm verify(buff, used, ROCKRIDGE, &fns); 337231200Smm 338231200Smm /* Verify joliet filenames. */ 339231200Smm fns.longest_len = 0; 340231200Smm fns.maxlen = fns.maxflen = fns.maxelen = 64; 341231200Smm fns.opt = ALLOW_LDOT; 342231200Smm verify(buff, used, JOLIET, &fns); 343231200Smm 344231200Smm /* Verify ISO9660 filenames. */ 345231200Smm fns.longest_len = 0; 346231200Smm fns.maxlen = 8+3+1; 347231200Smm fns.maxflen = 8; 348231200Smm fns.maxelen = 3; 349231200Smm fns.opt = UPPER_CASE_ONLY | ONE_DOT; 350231200Smm verify(buff, used, ISO9660, &fns); 351231200Smm 352231200Smm /* 353231200Smm * Create ISO image with iso-level=2. 354231200Smm */ 355231200Smm assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used, 356231200Smm "iso-level=2")); 357231200Smm 358231200Smm /* Verify rockridge filenames. */ 359231200Smm fns.longest_len = 0; 360231200Smm fns.maxlen = fns.maxflen = fns.maxelen = 255; 361231200Smm fns.opt = ALLOW_LDOT; 362231200Smm verify(buff, used, ROCKRIDGE, &fns); 363231200Smm 364231200Smm /* Verify joliet filenames. */ 365231200Smm fns.longest_len = 0; 366231200Smm fns.maxlen = fns.maxflen = fns.maxelen = 64; 367231200Smm fns.opt = ALLOW_LDOT; 368231200Smm verify(buff, used, JOLIET, &fns); 369231200Smm 370231200Smm /* Verify ISO9660 filenames. */ 371231200Smm fns.longest_len = 0; 372231200Smm fns.maxlen = 31; 373231200Smm fns.maxflen = 30; 374231200Smm fns.maxelen = 30; 375231200Smm fns.opt = UPPER_CASE_ONLY | ONE_DOT; 376231200Smm verify(buff, used, ISO9660, &fns); 377231200Smm 378231200Smm /* 379231200Smm * Create ISO image with iso-level=3. 380231200Smm */ 381231200Smm assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used, 382231200Smm "iso-level=3")); 383231200Smm 384231200Smm /* Verify rockridge filenames. */ 385231200Smm fns.longest_len = 0; 386231200Smm fns.maxlen = fns.maxflen = fns.maxelen = 255; 387231200Smm fns.opt = ALLOW_LDOT; 388231200Smm verify(buff, used, ROCKRIDGE, &fns); 389231200Smm 390231200Smm /* Verify joliet filenames. */ 391231200Smm fns.longest_len = 0; 392231200Smm fns.maxlen = fns.maxflen = fns.maxelen = 64; 393231200Smm fns.opt = ALLOW_LDOT; 394231200Smm verify(buff, used, JOLIET, &fns); 395231200Smm 396231200Smm /* Verify ISO9660 filenames. */ 397231200Smm fns.longest_len = 0; 398231200Smm fns.maxlen = 31; 399231200Smm fns.maxflen = 30; 400231200Smm fns.maxelen = 30; 401231200Smm fns.opt = UPPER_CASE_ONLY | ONE_DOT; 402231200Smm verify(buff, used, ISO9660, &fns); 403231200Smm 404231200Smm /* 405231200Smm * Create ISO image with iso-level=4. 406231200Smm */ 407231200Smm assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used, 408231200Smm "iso-level=4")); 409231200Smm 410231200Smm /* Verify rockridge filenames. */ 411231200Smm fns.longest_len = 0; 412231200Smm fns.maxlen = fns.maxflen = fns.maxelen = 255; 413231200Smm fns.opt = ALLOW_LDOT; 414231200Smm verify(buff, used, ROCKRIDGE, &fns); 415231200Smm 416231200Smm /* Verify joliet filenames. */ 417231200Smm fns.longest_len = 0; 418231200Smm fns.maxlen = fns.maxflen = fns.maxelen = 64; 419231200Smm fns.opt = ALLOW_LDOT; 420231200Smm verify(buff, used, JOLIET, &fns); 421231200Smm 422231200Smm /* Verify ISO9660 filenames. */ 423231200Smm fns.longest_len = 0; 424231200Smm fns.maxlen = fns.maxflen = fns.maxelen = 193; 425231200Smm fns.opt = ALLOW_LDOT; 426231200Smm verify(buff, used, ISO9660, &fns); 427231200Smm 428231200Smm /* 429231200Smm * Create ISO image with iso-level=4 and !rockridge. 430231200Smm */ 431231200Smm assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used, 432231200Smm "iso-level=4,!rockridge")); 433231200Smm 434231200Smm /* Verify joliet filenames. */ 435231200Smm fns.longest_len = 0; 436231200Smm fns.maxlen = fns.maxflen = fns.maxelen = 64; 437231200Smm fns.opt = ALLOW_LDOT; 438231200Smm verify(buff, used, JOLIET, &fns); 439231200Smm 440231200Smm /* Verify ISO9660 filenames. */ 441231200Smm fns.longest_len = 0; 442231200Smm fns.maxlen = fns.maxflen = fns.maxelen = 207; 443231200Smm fns.opt = ALLOW_LDOT; 444231200Smm verify(buff, used, ISO9660, &fns); 445231200Smm 446231200Smm /* 447231200Smm * Create ISO image with joliet=long. 448231200Smm */ 449231200Smm assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used, 450231200Smm "joliet=long")); 451231200Smm 452231200Smm /* Verify rockridge filenames. */ 453231200Smm fns.longest_len = 0; 454231200Smm fns.maxlen = fns.maxflen = fns.maxelen = 255; 455231200Smm fns.opt = ALLOW_LDOT; 456231200Smm verify(buff, used, ROCKRIDGE, &fns); 457231200Smm 458231200Smm /* Verify joliet filenames. */ 459231200Smm fns.longest_len = 0; 460231200Smm fns.maxlen = fns.maxflen = fns.maxelen = 103; 461231200Smm fns.opt = ALLOW_LDOT; 462231200Smm verify(buff, used, JOLIET, &fns); 463231200Smm 464231200Smm /* Verify ISO9660 filenames. */ 465231200Smm fns.longest_len = 0; 466231200Smm fns.maxlen = 8+3+1; 467231200Smm fns.maxflen = 8; 468231200Smm fns.maxelen = 3; 469231200Smm fns.opt = UPPER_CASE_ONLY | ONE_DOT; 470231200Smm verify(buff, used, ISO9660, &fns); 471231200Smm 472231200Smm free(fns.names); 473231200Smm free(buff); 474231200Smm} 475