2 * Copyright (c) 2009,2010 Michihiro NAKAJIMA
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
28 * Check that an ISO 9660 image is correctly created.
31 add_entry(struct archive *a, const char *fname, const char *sym)
33 struct archive_entry *ae;
35 assert((ae = archive_entry_new()) != NULL);
36 archive_entry_set_birthtime(ae, 2, 20);
37 archive_entry_set_atime(ae, 3, 30);
38 archive_entry_set_ctime(ae, 4, 40);
39 archive_entry_set_mtime(ae, 5, 50);
40 archive_entry_copy_pathname(ae, fname);
42 archive_entry_set_symlink(ae, sym);
43 archive_entry_set_mode(ae, S_IFREG | 0555);
44 archive_entry_set_size(ae, 0);
45 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
46 archive_entry_free(ae);
58 #define UPPER_CASE_ONLY 0x00001
59 #define ONE_DOT 0x00002
60 #define ALLOW_LDOT 0x00004
73 verify_file(struct archive *a, enum vtype type, struct fns *fns)
75 struct archive_entry *ae;
78 assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
79 if (type == ROCKRIDGE) {
80 assertEqualInt(2, archive_entry_birthtime(ae));
81 assertEqualInt(3, archive_entry_atime(ae));
82 assertEqualInt(4, archive_entry_ctime(ae));
84 assertEqualInt(0, archive_entry_birthtime_is_set(ae));
85 assertEqualInt(5, archive_entry_atime(ae));
86 assertEqualInt(5, archive_entry_ctime(ae));
88 assertEqualInt(5, archive_entry_mtime(ae));
89 if (type == ROCKRIDGE)
90 assert((S_IFREG | 0555) == archive_entry_mode(ae));
92 assert((S_IFREG | 0400) == archive_entry_mode(ae));
93 assertEqualInt(0, archive_entry_size(ae));
96 * Check if the same filename does not appear.
98 for (i = 0; i < fns->cnt; i++) {
100 const char *pathname = archive_entry_pathname(ae);
101 const char *symlinkname = archive_entry_symlink(ae);
104 if (symlinkname != NULL) {
105 length = strlen(symlinkname);
106 assert(length == 1 || length == 128 || length == 255);
107 assertEqualInt(symlinkname[length-1], 'x');
109 failure("Found duplicate for %s", pathname);
110 assert(strcmp(fns->names[i], pathname) != 0);
111 assert((length = strlen(pathname)) <= fns->maxlen);
112 if (length > fns->longest_len)
113 fns->longest_len = length;
114 p = strrchr(pathname, '.');
116 /* Check a length of file name. */
117 assert((size_t)(p - pathname) <= fns->maxflen);
118 /* Check a length of file extension. */
119 assert(strlen(p+1) <= fns->maxelen);
120 if (fns->opt & ONE_DOT) {
121 /* Do not have multi dot. */
122 assert(strchr(pathname, '.') == p);
125 for (p = pathname; *p; p++) {
126 if (fns->opt & UPPER_CASE_ONLY) {
127 /* Do not have any lower-case character. */
128 assert(*p < 'a' || *p > 'z');
132 if ((fns->opt & ALLOW_LDOT) == 0)
133 /* Do not have a dot at the first position. */
134 assert(*pathname != '.');
136 /* Save the filename which is appeared to use above next time. */
137 fns->names[fns->cnt++] = strdup(archive_entry_pathname(ae));
141 verify(unsigned char *buff, size_t used, enum vtype type, struct fns *fns)
144 struct archive_entry *ae;
150 assert((a = archive_read_new()) != NULL);
151 assertEqualIntA(a, 0, archive_read_support_format_all(a));
152 assertEqualIntA(a, 0, archive_read_support_filter_all(a));
154 assertA(0 == archive_read_set_option(a, NULL, "rockridge",
157 assertA(0 == archive_read_set_option(a, NULL, "joliet",
159 assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used));
162 * Read Root Directory
163 * Root Directory entry must be in ISO image.
165 assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
166 assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae));
167 assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae));
168 assertEqualString(".", archive_entry_pathname(ae));
171 assert((S_IFDIR | 0555) == archive_entry_mode(ae));
174 assert((S_IFDIR | 0700) == archive_entry_mode(ae));
177 assert((S_IFDIR | 0700) == archive_entry_mode(ae));
182 * Verify file status.
184 memset(fns->names, 0, sizeof(char *) * fns->alloc);
186 for (i = 0; i < fns->alloc; i++)
187 verify_file(a, type, fns);
188 for (i = 0; i < fns->alloc; i++)
190 assertEqualInt((int)fns->longest_len, (int)fns->maxlen);
193 * Verify the end of the archive.
195 assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
196 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
197 assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
201 create_iso_image(unsigned char *buff, size_t buffsize, size_t *used,
207 0, 1, 3, 5, 7, 8, 9, 29, 30, 31, 32,
208 62, 63, 64, 65, 101, 102, 103, 104,
209 191, 192, 193, 194, 204, 205, 206, 207, 208,
218 /* ISO9660 format: Create a new archive in memory. */
219 assert((a = archive_write_new()) != NULL);
220 assertA(0 == archive_write_set_format_iso9660(a));
221 assertA(0 == archive_write_add_filter_none(a));
222 assertA(0 == archive_write_set_option(a, NULL, "pad", NULL));
224 assertA(0 == archive_write_set_options(a, opt));
225 assertA(0 == archive_write_set_bytes_per_block(a, 1));
226 assertA(0 == archive_write_set_bytes_in_last_block(a, 1));
227 assertA(0 == archive_write_open_memory(a, buff, buffsize, used));
231 for (i = 0; i < (int)sizeof(sym128)-2; i++)
233 sym128[sizeof(sym128)-2] = 'x';
234 sym128[sizeof(sym128)-1] = '\0';
235 for (i = 0; i < (int)sizeof(sym255)-2; i++)
237 sym255[sizeof(sym255)-2] = 'x';
238 sym255[sizeof(sym255)-1] = '\0';
241 for (i = 0; lens[i] >= 0; i++) {
242 for (l = 0; l < lens[i]; l++) {
249 add_entry(a, fname1, NULL);
250 add_entry(a, fname2, sym1);
260 add_entry(a, fname1, sym128);
261 add_entry(a, fname2, sym255);
275 add_entry(a, fname1, NULL);
276 add_entry(a, fname2, sym1);
292 add_entry(a, fname1, sym128);
293 add_entry(a, fname2, sym255);
298 /* Close out the archive. */
299 assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
300 assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a));
305 DEFINE_TEST(test_write_format_iso9660_filename)
308 size_t buffsize = 120 * 2048;
313 buff = malloc(buffsize);
314 assert(buff != NULL);
317 memset(&fns, 0, sizeof(fns));
320 * Create ISO image with no option.
322 fcnt = create_iso_image(buff, buffsize, &used, NULL);
324 fns.names = (char **)malloc(sizeof(char *) * fcnt);
325 assert(fns.names != NULL);
326 if (fns.names == NULL) {
332 /* Verify rockridge filenames. */
334 fns.maxlen = fns.maxflen = fns.maxelen = 255;
335 fns.opt = ALLOW_LDOT;
336 verify(buff, used, ROCKRIDGE, &fns);
338 /* Verify joliet filenames. */
340 fns.maxlen = fns.maxflen = fns.maxelen = 64;
341 fns.opt = ALLOW_LDOT;
342 verify(buff, used, JOLIET, &fns);
344 /* Verify ISO9660 filenames. */
349 fns.opt = UPPER_CASE_ONLY | ONE_DOT;
350 verify(buff, used, ISO9660, &fns);
353 * Create ISO image with iso-level=2.
355 assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used,
358 /* Verify rockridge filenames. */
360 fns.maxlen = fns.maxflen = fns.maxelen = 255;
361 fns.opt = ALLOW_LDOT;
362 verify(buff, used, ROCKRIDGE, &fns);
364 /* Verify joliet filenames. */
366 fns.maxlen = fns.maxflen = fns.maxelen = 64;
367 fns.opt = ALLOW_LDOT;
368 verify(buff, used, JOLIET, &fns);
370 /* Verify ISO9660 filenames. */
375 fns.opt = UPPER_CASE_ONLY | ONE_DOT;
376 verify(buff, used, ISO9660, &fns);
379 * Create ISO image with iso-level=3.
381 assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used,
384 /* Verify rockridge filenames. */
386 fns.maxlen = fns.maxflen = fns.maxelen = 255;
387 fns.opt = ALLOW_LDOT;
388 verify(buff, used, ROCKRIDGE, &fns);
390 /* Verify joliet filenames. */
392 fns.maxlen = fns.maxflen = fns.maxelen = 64;
393 fns.opt = ALLOW_LDOT;
394 verify(buff, used, JOLIET, &fns);
396 /* Verify ISO9660 filenames. */
401 fns.opt = UPPER_CASE_ONLY | ONE_DOT;
402 verify(buff, used, ISO9660, &fns);
405 * Create ISO image with iso-level=4.
407 assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used,
410 /* Verify rockridge filenames. */
412 fns.maxlen = fns.maxflen = fns.maxelen = 255;
413 fns.opt = ALLOW_LDOT;
414 verify(buff, used, ROCKRIDGE, &fns);
416 /* Verify joliet filenames. */
418 fns.maxlen = fns.maxflen = fns.maxelen = 64;
419 fns.opt = ALLOW_LDOT;
420 verify(buff, used, JOLIET, &fns);
422 /* Verify ISO9660 filenames. */
424 fns.maxlen = fns.maxflen = fns.maxelen = 193;
425 fns.opt = ALLOW_LDOT;
426 verify(buff, used, ISO9660, &fns);
429 * Create ISO image with iso-level=4 and !rockridge.
431 assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used,
432 "iso-level=4,!rockridge"));
434 /* Verify joliet filenames. */
436 fns.maxlen = fns.maxflen = fns.maxelen = 64;
437 fns.opt = ALLOW_LDOT;
438 verify(buff, used, JOLIET, &fns);
440 /* Verify ISO9660 filenames. */
442 fns.maxlen = fns.maxflen = fns.maxelen = 207;
443 fns.opt = ALLOW_LDOT;
444 verify(buff, used, ISO9660, &fns);
447 * Create ISO image with joliet=long.
449 assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used,
452 /* Verify rockridge filenames. */
454 fns.maxlen = fns.maxflen = fns.maxelen = 255;
455 fns.opt = ALLOW_LDOT;
456 verify(buff, used, ROCKRIDGE, &fns);
458 /* Verify joliet filenames. */
460 fns.maxlen = fns.maxflen = fns.maxelen = 103;
461 fns.opt = ALLOW_LDOT;
462 verify(buff, used, JOLIET, &fns);
464 /* Verify ISO9660 filenames. */
469 fns.opt = UPPER_CASE_ONLY | ONE_DOT;
470 verify(buff, used, ISO9660, &fns);