]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/libarchive/libarchive/test/test_write_format_iso9660_filename.c
MFC r368207,368607:
[FreeBSD/stable/10.git] / contrib / libarchive / libarchive / test / test_write_format_iso9660_filename.c
1 /*-
2  * Copyright (c) 2009,2010 Michihiro NAKAJIMA
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
27 /*
28  * Check that an ISO 9660 image is correctly created.
29  */
30 static void
31 add_entry(struct archive *a, const char *fname, const char *sym)
32 {
33         struct archive_entry *ae;
34
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);
41         if (sym != NULL)
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);
47 }
48
49 struct fns {
50         size_t  maxlen;
51         size_t  longest_len;
52         size_t  maxflen;
53         size_t  maxelen;
54         size_t  alloc;
55         int     cnt;
56         char    **names;
57         int     opt;
58 #define UPPER_CASE_ONLY 0x00001
59 #define ONE_DOT         0x00002
60 #define ALLOW_LDOT      0x00004
61 };
62
63 enum vtype {
64         ROCKRIDGE,
65         JOLIET,
66         ISO9660
67 };
68
69 /*
70  * Verify file
71  */
72 static void
73 verify_file(struct archive *a, enum vtype type, struct fns *fns)
74 {
75         struct archive_entry *ae;
76         int i;
77
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));
83         } else {
84                 assertEqualInt(0, archive_entry_birthtime_is_set(ae));
85                 assertEqualInt(5, archive_entry_atime(ae));
86                 assertEqualInt(5, archive_entry_ctime(ae));
87         }
88         assertEqualInt(5, archive_entry_mtime(ae));
89         if (type == ROCKRIDGE)
90                 assert((S_IFREG | 0555) == archive_entry_mode(ae));
91         else
92                 assert((S_IFREG | 0400) == archive_entry_mode(ae));
93         assertEqualInt(0, archive_entry_size(ae));
94
95         /*
96          * Check if the same filename does not appear.
97          */
98         for (i = 0; i < fns->cnt; i++) {
99                 const char *p;
100                 const char *pathname = archive_entry_pathname(ae);
101                 const char *symlinkname = archive_entry_symlink(ae);
102                 size_t length;
103
104                 if (symlinkname != NULL) {
105                         length = strlen(symlinkname);
106                         assert(length == 1 || length == 128 || length == 255);
107                         assertEqualInt(symlinkname[length-1], 'x');
108                 }
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, '.');
115                 if (p != NULL) {
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);
123                         }
124                 }
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');
129                         } else
130                                 break;
131                 }
132                 if ((fns->opt & ALLOW_LDOT) == 0)
133                         /* Do not have a dot at the first position. */
134                         assert(*pathname != '.');
135         }
136         /* Save the filename which is appeared to use above next time. */
137         fns->names[fns->cnt++] = strdup(archive_entry_pathname(ae));
138 }
139
140 static void
141 verify(unsigned char *buff, size_t used, enum vtype type, struct fns *fns)
142 {
143         struct archive *a;
144         struct archive_entry *ae;
145         size_t i;
146
147         /*
148          * Read ISO image.
149          */
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));
153         if (type >= 1)
154                 assertA(0 == archive_read_set_option(a, NULL, "rockridge",
155                     NULL));
156         if (type >= 2)
157                 assertA(0 == archive_read_set_option(a, NULL, "joliet",
158                     NULL));
159         assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used));
160
161         /*
162          * Read Root Directory
163          * Root Directory entry must be in ISO image.
164          */
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));
169         switch (type) {
170         case ROCKRIDGE:
171                 assert((S_IFDIR | 0555) == archive_entry_mode(ae));
172                 break;
173         case JOLIET:
174                 assert((S_IFDIR | 0700) == archive_entry_mode(ae));
175                 break;
176         case ISO9660:
177                 assert((S_IFDIR | 0700) == archive_entry_mode(ae));
178                 break;
179         }
180
181         /*
182          * Verify file status.
183          */
184         memset(fns->names, 0, sizeof(char *) * fns->alloc);
185         fns->cnt = 0;
186         for (i = 0; i < fns->alloc; i++)
187                 verify_file(a, type, fns);
188         for (i = 0; i < fns->alloc; i++)
189                 free(fns->names[i]);
190         assertEqualInt((int)fns->longest_len, (int)fns->maxlen);
191
192         /*
193          * Verify the end of the archive.
194          */
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));
198 }
199
200 static int
201 create_iso_image(unsigned char *buff, size_t buffsize, size_t *used,
202     const char *opt)
203 {
204         struct archive *a;
205         int i, l, fcnt;
206         const int lens[] = {
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,
210                 252, 253, 254, 255,
211             -1 };
212         char fname1[256];
213         char fname2[256];
214         char sym1[2];
215         char sym128[129];
216         char sym255[256];
217
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));
223         if (opt)
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));
228
229         sym1[0] = 'x';
230         sym1[1] = '\0';
231         for (i = 0; i < (int)sizeof(sym128)-2; i++)
232                 sym128[i] = 'a';
233         sym128[sizeof(sym128)-2] = 'x';
234         sym128[sizeof(sym128)-1] = '\0';
235         for (i = 0; i < (int)sizeof(sym255)-2; i++)
236                 sym255[i] = 'a';
237         sym255[sizeof(sym255)-2] = 'x';
238         sym255[sizeof(sym255)-1] = '\0';
239
240         fcnt = 0;
241         for (i = 0; lens[i] >= 0; i++) {
242                 for (l = 0; l < lens[i]; l++) {
243                         fname1[l] = 'a';
244                         fname2[l] = 'A';
245                 }
246                 if (l > 0) {
247                         fname1[l] = '\0';
248                         fname2[l] = '\0';
249                         add_entry(a, fname1, NULL);
250                         add_entry(a, fname2, sym1);
251                         fcnt += 2;
252                 }
253                 if (l < 254) {
254                         fname1[l] = '.';
255                         fname1[l+1] = 'c';
256                         fname1[l+2] = '\0';
257                         fname2[l] = '.';
258                         fname2[l+1] = 'C';
259                         fname2[l+2] = '\0';
260                         add_entry(a, fname1, sym128);
261                         add_entry(a, fname2, sym255);
262                         fcnt += 2;
263                 }
264                 if (l < 252) {
265                         fname1[l] = '.';
266                         fname1[l+1] = 'p';
267                         fname1[l+2] = 'n';
268                         fname1[l+3] = 'g';
269                         fname1[l+4] = '\0';
270                         fname2[l] = '.';
271                         fname2[l+1] = 'P';
272                         fname2[l+2] = 'N';
273                         fname2[l+3] = 'G';
274                         fname2[l+4] = '\0';
275                         add_entry(a, fname1, NULL);
276                         add_entry(a, fname2, sym1);
277                         fcnt += 2;
278                 }
279                 if (l < 251) {
280                         fname1[l] = '.';
281                         fname1[l+1] = 'j';
282                         fname1[l+2] = 'p';
283                         fname1[l+3] = 'e';
284                         fname1[l+4] = 'g';
285                         fname1[l+5] = '\0';
286                         fname2[l] = '.';
287                         fname2[l+1] = 'J';
288                         fname2[l+2] = 'P';
289                         fname2[l+3] = 'E';
290                         fname2[l+4] = 'G';
291                         fname2[l+5] = '\0';
292                         add_entry(a, fname1, sym128);
293                         add_entry(a, fname2, sym255);
294                         fcnt += 2;
295                 }
296         }
297
298         /* Close out the archive. */
299         assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
300         assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a));
301
302         return (fcnt);
303 }
304
305 DEFINE_TEST(test_write_format_iso9660_filename)
306 {
307         unsigned char *buff;
308         size_t buffsize = 120 * 2048;
309         size_t used;
310         int fcnt;
311         struct fns fns;
312
313         buff = malloc(buffsize);
314         assert(buff != NULL);
315         if (buff == NULL)
316                 return;
317         memset(&fns, 0, sizeof(fns));
318
319         /*
320          * Create ISO image with no option.
321          */
322         fcnt = create_iso_image(buff, buffsize, &used, NULL);
323
324         fns.names = (char **)malloc(sizeof(char *) * fcnt);
325         assert(fns.names != NULL);
326         if (fns.names == NULL) {
327                 free(buff);
328                 return;
329         }
330         fns.alloc = fcnt;
331
332         /* Verify rockridge filenames. */
333         fns.longest_len = 0;
334         fns.maxlen = fns.maxflen = fns.maxelen = 255;
335         fns.opt = ALLOW_LDOT;
336         verify(buff, used, ROCKRIDGE, &fns);
337
338         /* Verify joliet filenames. */
339         fns.longest_len = 0;
340         fns.maxlen = fns.maxflen = fns.maxelen = 64;
341         fns.opt = ALLOW_LDOT;
342         verify(buff, used, JOLIET, &fns);
343
344         /* Verify ISO9660 filenames. */
345         fns.longest_len = 0;
346         fns.maxlen = 8+3+1;
347         fns.maxflen = 8;
348         fns.maxelen = 3;
349         fns.opt = UPPER_CASE_ONLY | ONE_DOT;
350         verify(buff, used, ISO9660, &fns);
351
352         /*
353          * Create ISO image with iso-level=2.
354          */
355         assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used,
356             "iso-level=2"));
357
358         /* Verify rockridge filenames. */
359         fns.longest_len = 0;
360         fns.maxlen = fns.maxflen = fns.maxelen = 255;
361         fns.opt = ALLOW_LDOT;
362         verify(buff, used, ROCKRIDGE, &fns);
363
364         /* Verify joliet filenames. */
365         fns.longest_len = 0;
366         fns.maxlen = fns.maxflen = fns.maxelen = 64;
367         fns.opt = ALLOW_LDOT;
368         verify(buff, used, JOLIET, &fns);
369
370         /* Verify ISO9660 filenames. */
371         fns.longest_len = 0;
372         fns.maxlen = 31;
373         fns.maxflen = 30;
374         fns.maxelen = 30;
375         fns.opt = UPPER_CASE_ONLY | ONE_DOT;
376         verify(buff, used, ISO9660, &fns);
377
378         /*
379          * Create ISO image with iso-level=3.
380          */
381         assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used,
382             "iso-level=3"));
383
384         /* Verify rockridge filenames. */
385         fns.longest_len = 0;
386         fns.maxlen = fns.maxflen = fns.maxelen = 255;
387         fns.opt = ALLOW_LDOT;
388         verify(buff, used, ROCKRIDGE, &fns);
389
390         /* Verify joliet filenames. */
391         fns.longest_len = 0;
392         fns.maxlen = fns.maxflen = fns.maxelen = 64;
393         fns.opt = ALLOW_LDOT;
394         verify(buff, used, JOLIET, &fns);
395
396         /* Verify ISO9660 filenames. */
397         fns.longest_len = 0;
398         fns.maxlen = 31;
399         fns.maxflen = 30;
400         fns.maxelen = 30;
401         fns.opt = UPPER_CASE_ONLY | ONE_DOT;
402         verify(buff, used, ISO9660, &fns);
403
404         /*
405          * Create ISO image with iso-level=4.
406          */
407         assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used,
408             "iso-level=4"));
409
410         /* Verify rockridge filenames. */
411         fns.longest_len = 0;
412         fns.maxlen = fns.maxflen = fns.maxelen = 255;
413         fns.opt = ALLOW_LDOT;
414         verify(buff, used, ROCKRIDGE, &fns);
415
416         /* Verify joliet filenames. */
417         fns.longest_len = 0;
418         fns.maxlen = fns.maxflen = fns.maxelen = 64;
419         fns.opt = ALLOW_LDOT;
420         verify(buff, used, JOLIET, &fns);
421
422         /* Verify ISO9660 filenames. */
423         fns.longest_len = 0;
424         fns.maxlen = fns.maxflen = fns.maxelen = 193;
425         fns.opt = ALLOW_LDOT;
426         verify(buff, used, ISO9660, &fns);
427
428         /*
429          * Create ISO image with iso-level=4 and !rockridge.
430          */
431         assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used,
432             "iso-level=4,!rockridge"));
433
434         /* Verify joliet filenames. */
435         fns.longest_len = 0;
436         fns.maxlen = fns.maxflen = fns.maxelen = 64;
437         fns.opt = ALLOW_LDOT;
438         verify(buff, used, JOLIET, &fns);
439
440         /* Verify ISO9660 filenames. */
441         fns.longest_len = 0;
442         fns.maxlen = fns.maxflen = fns.maxelen = 207;
443         fns.opt = ALLOW_LDOT;
444         verify(buff, used, ISO9660, &fns);
445
446         /*
447          * Create ISO image with joliet=long.
448          */
449         assertEqualInt(fcnt, create_iso_image(buff, buffsize, &used,
450             "joliet=long"));
451
452         /* Verify rockridge filenames. */
453         fns.longest_len = 0;
454         fns.maxlen = fns.maxflen = fns.maxelen = 255;
455         fns.opt = ALLOW_LDOT;
456         verify(buff, used, ROCKRIDGE, &fns);
457
458         /* Verify joliet filenames. */
459         fns.longest_len = 0;
460         fns.maxlen = fns.maxflen = fns.maxelen = 103;
461         fns.opt = ALLOW_LDOT;
462         verify(buff, used, JOLIET, &fns);
463
464         /* Verify ISO9660 filenames. */
465         fns.longest_len = 0;
466         fns.maxlen = 8+3+1;
467         fns.maxflen = 8;
468         fns.maxelen = 3;
469         fns.opt = UPPER_CASE_ONLY | ONE_DOT;
470         verify(buff, used, ISO9660, &fns);
471
472         free(fns.names);
473         free(buff);
474 }