]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/libarchive/libarchive/test/test_read_disk_directory_traversals.c
MFstable/11 r310569:
[FreeBSD/stable/10.git] / contrib / libarchive / libarchive / test / test_read_disk_directory_traversals.c
1 /*-
2  * Copyright (c) 2010-2012 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 __FBSDID("$FreeBSD$");
27
28 #include <limits.h>
29 #if defined(_WIN32) && !defined(__CYGWIN__)
30 # if !defined(__BORLANDC__)
31 #  define getcwd _getcwd
32 # endif
33 #endif
34
35 /*
36  * Test if the current filesytem is mounted with noatime option.
37  */
38 static int
39 atimeIsUpdated(void)
40 {
41         const char *fn = "fs_noatime";
42         struct stat st;
43
44         if (!assertMakeFile(fn, 0666, "a"))
45                 return (0);
46         if (!assertUtimes(fn, 1, 0, 1, 0))
47                 return (0);
48         /* Test the file contents in order to update its atime. */
49         if (!assertTextFileContents("a", fn))
50                 return (0);
51         if (stat(fn, &st) != 0)
52                 return (0);
53         /* Is atime updated? */
54         if (st.st_atime > 1)
55                 return (1);
56         return (0);
57 }
58
59 static void
60 test_basic(void)
61 {
62         struct archive *a;
63         struct archive_entry *ae;
64         const void *p;
65         char *initial_cwd, *cwd;
66         size_t size;
67         int64_t offset;
68         int file_count;
69 #if defined(_WIN32) && !defined(__CYGWIN__)
70         wchar_t *wcwd, *wp, *fullpath;
71 #endif
72
73         assertMakeDir("dir1", 0755);
74         assertMakeFile("dir1/file1", 0644, "0123456789");
75         assertMakeFile("dir1/file2", 0644, "hello world");
76         assertMakeDir("dir1/sub1", 0755);
77         assertMakeFile("dir1/sub1/file1", 0644, "0123456789");
78         assertMakeDir("dir1/sub2", 0755);
79         assertMakeFile("dir1/sub2/file1", 0644, "0123456789");
80         assertMakeFile("dir1/sub2/file2", 0644, "0123456789");
81         assertMakeDir("dir1/sub2/sub1", 0755);
82         assertMakeDir("dir1/sub2/sub2", 0755);
83         assertMakeDir("dir1/sub2/sub3", 0755);
84         assertMakeFile("dir1/sub2/sub3/file", 0644, "xyz");
85         file_count = 12;
86
87         assert((ae = archive_entry_new()) != NULL);
88         assert((a = archive_read_disk_new()) != NULL);
89         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1"));
90
91         while (file_count--) {
92                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
93                 if (strcmp(archive_entry_pathname(ae), "dir1") == 0) {
94                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
95                         assertEqualInt(1, archive_read_disk_can_descend(a));
96                 } else if (strcmp(archive_entry_pathname(ae),
97                     "dir1/file1") == 0) {
98                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
99                         assertEqualInt(archive_entry_size(ae), 10);
100                         assertEqualIntA(a, ARCHIVE_OK,
101                             archive_read_data_block(a, &p, &size, &offset));
102                         assertEqualInt((int)size, 10);
103                         assertEqualInt((int)offset, 0);
104                         assertEqualMem(p, "0123456789", 10);
105                         assertEqualInt(ARCHIVE_EOF,
106                             archive_read_data_block(a, &p, &size, &offset));
107                         assertEqualInt((int)size, 0);
108                         assertEqualInt((int)offset, 10);
109                         assertEqualInt(0, archive_read_disk_can_descend(a));
110                 } else if (strcmp(archive_entry_pathname(ae),
111                     "dir1/file2") == 0) {
112                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
113                         assertEqualInt(archive_entry_size(ae), 11);
114                         assertEqualIntA(a, ARCHIVE_OK,
115                             archive_read_data_block(a, &p, &size, &offset));
116                         assertEqualInt((int)size, 11);
117                         assertEqualInt((int)offset, 0);
118                         assertEqualMem(p, "hello world", 11);
119                         assertEqualInt(ARCHIVE_EOF,
120                             archive_read_data_block(a, &p, &size, &offset));
121                         assertEqualInt((int)size, 0);
122                         assertEqualInt((int)offset, 11);
123                         assertEqualInt(0, archive_read_disk_can_descend(a));
124                 } else if (strcmp(archive_entry_pathname(ae),
125                     "dir1/sub1") == 0) {
126                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
127                         assertEqualInt(1, archive_read_disk_can_descend(a));
128                 } else if (strcmp(archive_entry_pathname(ae),
129                     "dir1/sub1/file1") == 0) {
130                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
131                         assertEqualInt(archive_entry_size(ae), 10);
132                         assertEqualIntA(a, ARCHIVE_OK,
133                             archive_read_data_block(a, &p, &size, &offset));
134                         assertEqualInt((int)size, 10);
135                         assertEqualInt((int)offset, 0);
136                         assertEqualMem(p, "0123456789", 10);
137                         assertEqualInt(ARCHIVE_EOF,
138                             archive_read_data_block(a, &p, &size, &offset));
139                         assertEqualInt((int)size, 0);
140                         assertEqualInt((int)offset, 10);
141                         assertEqualInt(0, archive_read_disk_can_descend(a));
142                 } else if (strcmp(archive_entry_pathname(ae),
143                     "dir1/sub2") == 0) {
144                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
145                         assertEqualInt(1, archive_read_disk_can_descend(a));
146                 } else if (strcmp(archive_entry_pathname(ae),
147                     "dir1/sub2/file1") == 0) {
148                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
149                         assertEqualInt(archive_entry_size(ae), 10);
150                         assertEqualIntA(a, ARCHIVE_OK,
151                             archive_read_data_block(a, &p, &size, &offset));
152                         assertEqualInt((int)size, 10);
153                         assertEqualInt((int)offset, 0);
154                         assertEqualMem(p, "0123456789", 10);
155                         assertEqualInt(ARCHIVE_EOF,
156                             archive_read_data_block(a, &p, &size, &offset));
157                         assertEqualInt((int)size, 0);
158                         assertEqualInt((int)offset, 10);
159                         assertEqualInt(0, archive_read_disk_can_descend(a));
160                 } else if (strcmp(archive_entry_pathname(ae),
161                     "dir1/sub2/file2") == 0) {
162                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
163                         assertEqualInt(archive_entry_size(ae), 10);
164                         assertEqualIntA(a, ARCHIVE_OK,
165                             archive_read_data_block(a, &p, &size, &offset));
166                         assertEqualInt((int)size, 10);
167                         assertEqualInt((int)offset, 0);
168                         assertEqualMem(p, "0123456789", 10);
169                         assertEqualInt(ARCHIVE_EOF,
170                             archive_read_data_block(a, &p, &size, &offset));
171                         assertEqualInt((int)size, 0);
172                         assertEqualInt((int)offset, 10);
173                         assertEqualInt(0, archive_read_disk_can_descend(a));
174                 } else if (strcmp(archive_entry_pathname(ae),
175                     "dir1/sub2/sub1") == 0) {
176                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
177                         assertEqualInt(1, archive_read_disk_can_descend(a));
178                 } else if (strcmp(archive_entry_pathname(ae),
179                     "dir1/sub2/sub2") == 0) {
180                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
181                         assertEqualInt(1, archive_read_disk_can_descend(a));
182                 } else if (strcmp(archive_entry_pathname(ae),
183                     "dir1/sub2/sub3") == 0) {
184                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
185                         assertEqualInt(1, archive_read_disk_can_descend(a));
186                 } else if (strcmp(archive_entry_pathname(ae),
187                     "dir1/sub2/sub3/file") == 0) {
188                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
189                         assertEqualInt(archive_entry_size(ae), 3);
190                         assertEqualIntA(a, ARCHIVE_OK,
191                             archive_read_data_block(a, &p, &size, &offset));
192                         assertEqualInt((int)size, 3);
193                         assertEqualInt((int)offset, 0);
194                         assertEqualMem(p, "xyz", 3);
195                         assertEqualInt(ARCHIVE_EOF,
196                             archive_read_data_block(a, &p, &size, &offset));
197                         assertEqualInt((int)size, 0);
198                         assertEqualInt((int)offset, 3);
199                         assertEqualInt(0, archive_read_disk_can_descend(a));
200                 }
201                 if (archive_entry_filetype(ae) == AE_IFDIR) {
202                         /* Descend into the current object */
203                         assertEqualIntA(a, ARCHIVE_OK,
204                             archive_read_disk_descend(a));
205                 }
206         }
207         /* There is no entry. */
208         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
209
210         /* Close the disk object. */
211         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
212
213         /*
214          * Test that call archive_read_disk_open_w, wchar_t version.
215          */
216         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, L"dir1"));
217
218         file_count = 12;
219         while (file_count--) {
220                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
221                 if (wcscmp(archive_entry_pathname_w(ae), L"dir1") == 0) {
222                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
223                         assertEqualInt(1, archive_read_disk_can_descend(a));
224                 } else if (wcscmp(archive_entry_pathname_w(ae),
225                     L"dir1/file1") == 0) {
226                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
227                         assertEqualInt(archive_entry_size(ae), 10);
228                         assertEqualIntA(a, ARCHIVE_OK,
229                             archive_read_data_block(a, &p, &size, &offset));
230                         assertEqualInt((int)size, 10);
231                         assertEqualInt((int)offset, 0);
232                         assertEqualMem(p, "0123456789", 10);
233                         assertEqualInt(ARCHIVE_EOF,
234                             archive_read_data_block(a, &p, &size, &offset));
235                         assertEqualInt((int)size, 0);
236                         assertEqualInt((int)offset, 10);
237                         assertEqualInt(0, archive_read_disk_can_descend(a));
238                 } else if (wcscmp(archive_entry_pathname_w(ae),
239                     L"dir1/file2") == 0) {
240                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
241                         assertEqualInt(archive_entry_size(ae), 11);
242                         assertEqualIntA(a, ARCHIVE_OK,
243                             archive_read_data_block(a, &p, &size, &offset));
244                         assertEqualInt((int)size, 11);
245                         assertEqualInt((int)offset, 0);
246                         assertEqualMem(p, "hello world", 11);
247                         assertEqualInt(ARCHIVE_EOF,
248                             archive_read_data_block(a, &p, &size, &offset));
249                         assertEqualInt((int)size, 0);
250                         assertEqualInt((int)offset, 11);
251                         assertEqualInt(0, archive_read_disk_can_descend(a));
252                 } else if (wcscmp(archive_entry_pathname_w(ae),
253                     L"dir1/sub1") == 0) {
254                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
255                         assertEqualInt(1, archive_read_disk_can_descend(a));
256                 } else if (wcscmp(archive_entry_pathname_w(ae),
257                     L"dir1/sub1/file1") == 0) {
258                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
259                         assertEqualInt(archive_entry_size(ae), 10);
260                         assertEqualIntA(a, ARCHIVE_OK,
261                             archive_read_data_block(a, &p, &size, &offset));
262                         assertEqualInt((int)size, 10);
263                         assertEqualInt((int)offset, 0);
264                         assertEqualMem(p, "0123456789", 10);
265                         assertEqualInt(ARCHIVE_EOF,
266                             archive_read_data_block(a, &p, &size, &offset));
267                         assertEqualInt((int)size, 0);
268                         assertEqualInt((int)offset, 10);
269                         assertEqualInt(0, archive_read_disk_can_descend(a));
270                 } else if (wcscmp(archive_entry_pathname_w(ae),
271                     L"dir1/sub2") == 0) {
272                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
273                         assertEqualInt(1, archive_read_disk_can_descend(a));
274                 } else if (wcscmp(archive_entry_pathname_w(ae),
275                     L"dir1/sub2/file1") == 0) {
276                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
277                         assertEqualInt(archive_entry_size(ae), 10);
278                         assertEqualIntA(a, ARCHIVE_OK,
279                             archive_read_data_block(a, &p, &size, &offset));
280                         assertEqualInt((int)size, 10);
281                         assertEqualInt((int)offset, 0);
282                         assertEqualMem(p, "0123456789", 10);
283                         assertEqualInt(ARCHIVE_EOF,
284                             archive_read_data_block(a, &p, &size, &offset));
285                         assertEqualInt((int)size, 0);
286                         assertEqualInt((int)offset, 10);
287                         assertEqualInt(0, archive_read_disk_can_descend(a));
288                 } else if (wcscmp(archive_entry_pathname_w(ae),
289                     L"dir1/sub2/file2") == 0) {
290                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
291                         assertEqualInt(archive_entry_size(ae), 10);
292                         assertEqualIntA(a, ARCHIVE_OK,
293                             archive_read_data_block(a, &p, &size, &offset));
294                         assertEqualInt((int)size, 10);
295                         assertEqualInt((int)offset, 0);
296                         assertEqualMem(p, "0123456789", 10);
297                         assertEqualInt(ARCHIVE_EOF,
298                             archive_read_data_block(a, &p, &size, &offset));
299                         assertEqualInt((int)size, 0);
300                         assertEqualInt((int)offset, 10);
301                         assertEqualInt(0, archive_read_disk_can_descend(a));
302                 } else if (wcscmp(archive_entry_pathname_w(ae),
303                     L"dir1/sub2/sub1") == 0) {
304                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
305                         assertEqualInt(1, archive_read_disk_can_descend(a));
306                 } else if (wcscmp(archive_entry_pathname_w(ae),
307                     L"dir1/sub2/sub2") == 0) {
308                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
309                         assertEqualInt(1, archive_read_disk_can_descend(a));
310                 } else if (wcscmp(archive_entry_pathname_w(ae),
311                     L"dir1/sub2/sub3") == 0) {
312                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
313                         assertEqualInt(1, archive_read_disk_can_descend(a));
314                 } else if (wcscmp(archive_entry_pathname_w(ae),
315                     L"dir1/sub2/sub3/file") == 0) {
316                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
317                         assertEqualInt(archive_entry_size(ae), 3);
318                         assertEqualIntA(a, ARCHIVE_OK,
319                             archive_read_data_block(a, &p, &size, &offset));
320                         assertEqualInt((int)size, 3);
321                         assertEqualInt((int)offset, 0);
322                         assertEqualMem(p, "xyz", 3);
323                         assertEqualInt(ARCHIVE_EOF,
324                             archive_read_data_block(a, &p, &size, &offset));
325                         assertEqualInt((int)size, 0);
326                         assertEqualInt((int)offset, 3);
327                         assertEqualInt(0, archive_read_disk_can_descend(a));
328                 }
329                 if (archive_entry_filetype(ae) == AE_IFDIR) {
330                         /* Descend into the current object */
331                         assertEqualIntA(a, ARCHIVE_OK,
332                             archive_read_disk_descend(a));
333                 }
334         }
335         /* There is no entry. */
336         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
337
338         /* Close the disk object. */
339         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
340
341         /*
342          * Test that call archive_read_disk_open with a regular file.
343          */
344         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1/file1"));
345
346         /* dir1/file1 */
347         assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
348         assertEqualInt(0, archive_read_disk_can_descend(a));
349         assertEqualString(archive_entry_pathname(ae), "dir1/file1");
350         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
351         assertEqualInt(archive_entry_size(ae), 10);
352         assertEqualIntA(a, ARCHIVE_OK,
353             archive_read_data_block(a, &p, &size, &offset));
354         assertEqualInt((int)size, 10);
355         assertEqualInt((int)offset, 0);
356         assertEqualMem(p, "0123456789", 10);
357
358         /* There is no entry. */
359         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
360
361         /* Close the disk object. */
362         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
363
364
365 #if defined(_WIN32) && !defined(__CYGWIN__)
366         /*
367          * Test for wildcard '*' or '?'
368          */
369         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1/*1"));
370
371         /* dir1/file1 */
372         assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
373         assertEqualInt(0, archive_read_disk_can_descend(a));
374         assertEqualString(archive_entry_pathname(ae), "dir1/file1");
375         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
376         assertEqualInt(archive_entry_size(ae), 10);
377         assertEqualIntA(a, ARCHIVE_OK,
378             archive_read_data_block(a, &p, &size, &offset));
379         assertEqualInt((int)size, 10);
380         assertEqualInt((int)offset, 0);
381         assertEqualMem(p, "0123456789", 10);
382
383         /* dir1/sub1 */
384         assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
385         assertEqualInt(1, archive_read_disk_can_descend(a));
386         assertEqualString(archive_entry_pathname(ae), "dir1/sub1");
387         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
388
389         /* Descend into the current object */
390         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a));
391
392         /* dir1/sub1/file1 */
393         assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
394         assertEqualInt(0, archive_read_disk_can_descend(a));
395         assertEqualString(archive_entry_pathname(ae), "dir1/sub1/file1");
396         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
397         assertEqualInt(archive_entry_size(ae), 10);
398         assertEqualIntA(a, ARCHIVE_OK,
399             archive_read_data_block(a, &p, &size, &offset));
400         assertEqualInt((int)size, 10);
401         assertEqualInt((int)offset, 0);
402         assertEqualMem(p, "0123456789", 10);
403
404         /* There is no entry. */
405         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
406
407         /* Close the disk object. */
408         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
409
410         /*
411          * Test for a full-path beginning with "//?/"
412          */
413         wcwd = _wgetcwd(NULL, 0);
414         fullpath = malloc(sizeof(wchar_t) * (wcslen(wcwd) + 32));
415         wcscpy(fullpath, L"//?/");
416         wcscat(fullpath, wcwd);
417         wcscat(fullpath, L"/dir1/file1");
418         free(wcwd);
419         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, fullpath));
420         while ((wcwd = wcschr(fullpath, L'\\')) != NULL)
421                 *wcwd = L'/';
422
423         /* dir1/file1 */
424         assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
425         assertEqualInt(0, archive_read_disk_can_descend(a));
426         assertEqualWString(archive_entry_pathname_w(ae), fullpath);
427         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
428         assertEqualInt(archive_entry_size(ae), 10);
429         assertEqualIntA(a, ARCHIVE_OK,
430             archive_read_data_block(a, &p, &size, &offset));
431         assertEqualInt((int)size, 10);
432         assertEqualInt((int)offset, 0);
433         assertEqualMem(p, "0123456789", 10);
434
435         /* There is no entry. */
436         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
437
438         /* Close the disk object. */
439         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
440         free(fullpath);
441
442         /*
443          * Test for wild card '*' or '?' with "//?/" prefix.
444          */
445         wcwd = _wgetcwd(NULL, 0);
446         fullpath = malloc(sizeof(wchar_t) * (wcslen(wcwd) + 32));
447         wcscpy(fullpath, L"//?/");
448         wcscat(fullpath, wcwd);
449         wcscat(fullpath, L"/dir1/*1");
450         free(wcwd);
451         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, fullpath));
452         while ((wcwd = wcschr(fullpath, L'\\')) != NULL)
453                 *wcwd = L'/';
454
455         /* dir1/file1 */
456         wp = wcsrchr(fullpath, L'/');
457         wcscpy(wp+1, L"file1");
458         assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
459         assertEqualInt(0, archive_read_disk_can_descend(a));
460         assertEqualWString(archive_entry_pathname_w(ae), fullpath);
461         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
462         assertEqualInt(archive_entry_size(ae), 10);
463         assertEqualIntA(a, ARCHIVE_OK,
464             archive_read_data_block(a, &p, &size, &offset));
465         assertEqualInt((int)size, 10);
466         assertEqualInt((int)offset, 0);
467         assertEqualMem(p, "0123456789", 10);
468
469         /* dir1/sub1 */
470         wcscpy(wp+1, L"sub1");
471         assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
472         assertEqualInt(1, archive_read_disk_can_descend(a));
473         assertEqualWString(archive_entry_pathname_w(ae), fullpath);
474         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
475
476         /* Descend into the current object */
477         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a));
478
479         /* dir1/sub1/file1 */
480         wcscpy(wp+1, L"sub1/file1");
481         assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
482         assertEqualInt(0, archive_read_disk_can_descend(a));
483         assertEqualWString(archive_entry_pathname_w(ae), fullpath);
484         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
485         assertEqualInt(archive_entry_size(ae), 10);
486         assertEqualIntA(a, ARCHIVE_OK,
487             archive_read_data_block(a, &p, &size, &offset));
488         assertEqualInt((int)size, 10);
489         assertEqualInt((int)offset, 0);
490         assertEqualMem(p, "0123456789", 10);
491
492         /* There is no entry. */
493         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
494
495         /* Close the disk object. */
496         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
497         free(fullpath);
498
499 #endif
500
501         /*
502          * We should be on the initial directory where we performed
503          * archive_read_disk_new() after we perfome archive_read_free()
504          *  even if we broke off the directory traversals.
505          */
506
507         /* Save current working directory. */
508 #ifdef PATH_MAX
509         initial_cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
510 #else
511         initial_cwd = getcwd(NULL, 0);
512 #endif
513
514         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1"));
515
516         /* Step in a deep directory. */
517         file_count = 12;
518         while (file_count--) {
519                 assertEqualIntA(a, ARCHIVE_OK,
520                     archive_read_next_header2(a, ae));
521                 if (strcmp(archive_entry_pathname(ae),
522                     "dir1/sub1/file1") == 0)
523                         /*
524                          * We are on an another directory at this time.
525                          */
526                         break;
527                 if (archive_entry_filetype(ae) == AE_IFDIR) {
528                         /* Descend into the current object */
529                         assertEqualIntA(a, ARCHIVE_OK,
530                             archive_read_disk_descend(a));
531                 }
532         }
533         /* Destroy the disk object. */
534         assertEqualInt(ARCHIVE_OK, archive_read_free(a));
535
536         /* We should be on the initial working directory. */
537         failure(
538             "Current working directory does not return to the initial"
539             "directory");
540 #ifdef PATH_MAX
541         cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
542 #else
543         cwd = getcwd(NULL, 0);
544 #endif
545         assertEqualString(initial_cwd, cwd);
546         free(initial_cwd);
547         free(cwd);
548
549         archive_entry_free(ae);
550 }
551
552 static void
553 test_symlink_hybrid(void)
554 {
555         struct archive *a;
556         struct archive_entry *ae;
557         const void *p;
558         size_t size;
559         int64_t offset;
560         int file_count;
561
562         if (!canSymlink()) {
563                 skipping("Can't test symlinks on this filesystem");
564                 return;
565         }
566
567         /*
568          * Create a sample archive.
569          */
570         assertMakeDir("h", 0755);
571         assertChdir("h");
572         assertMakeDir("d1", 0755);
573         assertMakeSymlink("ld1", "d1");
574         assertMakeFile("d1/file1", 0644, "d1/file1");
575         assertMakeFile("d1/file2", 0644, "d1/file2");
576         assertMakeSymlink("d1/link1", "file1");
577         assertMakeSymlink("d1/linkX", "fileX");
578         assertMakeSymlink("link2", "d1/file2");
579         assertMakeSymlink("linkY", "d1/fileY");
580         assertChdir("..");
581
582         assert((ae = archive_entry_new()) != NULL);
583         assert((a = archive_read_disk_new()) != NULL);
584         assertEqualIntA(a, ARCHIVE_OK,
585             archive_read_disk_set_symlink_hybrid(a));
586
587         /*
588          * Specified file is a symbolic link file.
589          */
590         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "h/ld1"));
591         file_count = 5;
592
593         while (file_count--) {
594                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
595                 if (strcmp(archive_entry_pathname(ae), "h/ld1") == 0) {
596                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
597                 } else if (strcmp(archive_entry_pathname(ae),
598                     "h/ld1/file1") == 0) {
599                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
600                         assertEqualInt(archive_entry_size(ae), 8);
601                         assertEqualIntA(a, ARCHIVE_OK,
602                             archive_read_data_block(a, &p, &size, &offset));
603                         assertEqualInt((int)size, 8);
604                         assertEqualInt((int)offset, 0);
605                         assertEqualMem(p, "d1/file1", 8);
606                         assertEqualInt(ARCHIVE_EOF,
607                             archive_read_data_block(a, &p, &size, &offset));
608                         assertEqualInt((int)size, 0);
609                         assertEqualInt((int)offset, 8);
610                 } else if (strcmp(archive_entry_pathname(ae),
611                     "h/ld1/file2") == 0) {
612                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
613                         assertEqualInt(archive_entry_size(ae), 8);
614                         assertEqualIntA(a, ARCHIVE_OK,
615                             archive_read_data_block(a, &p, &size, &offset));
616                         assertEqualInt((int)size, 8);
617                         assertEqualInt((int)offset, 0);
618                         assertEqualMem(p, "d1/file2", 8);
619                         assertEqualInt(ARCHIVE_EOF,
620                             archive_read_data_block(a, &p, &size, &offset));
621                         assertEqualInt((int)size, 0);
622                         assertEqualInt((int)offset, 8);
623                 } else if (strcmp(archive_entry_pathname(ae),
624                     "h/ld1/link1") == 0) {
625                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
626                 } else if (strcmp(archive_entry_pathname(ae),
627                     "h/ld1/linkX") == 0) {
628                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
629                 }
630                 if (archive_entry_filetype(ae) == AE_IFDIR) {
631                         /* Descend into the current object */
632                         assertEqualIntA(a, ARCHIVE_OK,
633                             archive_read_disk_descend(a));
634                 }
635         }
636         /* There is no entry. */
637         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
638         /* Close the disk object. */
639         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
640
641         /*
642          * Specified file is a directory and it has symbolic files.
643          */
644         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "h"));
645         file_count = 9;
646
647         while (file_count--) {
648                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
649                 if (strcmp(archive_entry_pathname(ae), "h") == 0) {
650                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
651                 } else if (strcmp(archive_entry_pathname(ae), "h/d1") == 0) {
652                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
653                 } else if (strcmp(archive_entry_pathname(ae),
654                     "h/d1/file1") == 0) {
655                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
656                         assertEqualInt(archive_entry_size(ae), 8);
657                         assertEqualIntA(a, ARCHIVE_OK,
658                             archive_read_data_block(a, &p, &size, &offset));
659                         assertEqualInt((int)size, 8);
660                         assertEqualInt((int)offset, 0);
661                         assertEqualMem(p, "d1/file1", 8);
662                         assertEqualInt(ARCHIVE_EOF,
663                             archive_read_data_block(a, &p, &size, &offset));
664                         assertEqualInt((int)size, 0);
665                         assertEqualInt((int)offset, 8);
666                 } else if (strcmp(archive_entry_pathname(ae),
667                     "h/d1/file2") == 0) {
668                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
669                         assertEqualInt(archive_entry_size(ae), 8);
670                         assertEqualIntA(a, ARCHIVE_OK,
671                             archive_read_data_block(a, &p, &size, &offset));
672                         assertEqualInt((int)size, 8);
673                         assertEqualInt((int)offset, 0);
674                         assertEqualMem(p, "d1/file2", 8);
675                         assertEqualInt(ARCHIVE_EOF,
676                             archive_read_data_block(a, &p, &size, &offset));
677                         assertEqualInt((int)size, 0);
678                         assertEqualInt((int)offset, 8);
679                 } else if (strcmp(archive_entry_pathname(ae), "h/ld1") == 0) {
680                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
681                 } else if (strcmp(archive_entry_pathname(ae),
682                     "h/d1/link1") == 0) {
683                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
684                 } else if (strcmp(archive_entry_pathname(ae),
685                     "h/d1/linkX") == 0) {
686                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
687                 } else if (strcmp(archive_entry_pathname(ae),
688                     "h/link2") == 0) {
689                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
690                 } else if (strcmp(archive_entry_pathname(ae),
691                     "h/linkY") == 0) {
692                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
693                 }
694                 if (archive_entry_filetype(ae) == AE_IFDIR) {
695                         /* Descend into the current object */
696                         assertEqualIntA(a, ARCHIVE_OK,
697                             archive_read_disk_descend(a));
698                 }
699         }
700         /* There is no entry. */
701         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
702         /* Close the disk object. */
703         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
704         /* Destroy the disk object. */
705         assertEqualInt(ARCHIVE_OK, archive_read_free(a));
706         archive_entry_free(ae);
707 }
708
709 static void
710 test_symlink_logical(void)
711 {
712         struct archive *a;
713         struct archive_entry *ae;
714         const void *p;
715         size_t size;
716         int64_t offset;
717         int file_count;
718
719         if (!canSymlink()) {
720                 skipping("Can't test symlinks on this filesystem");
721                 return;
722         }
723
724         /*
725          * Create a sample archive.
726          */
727         assertMakeDir("l", 0755);
728         assertChdir("l");
729         assertMakeDir("d1", 0755);
730         assertMakeSymlink("ld1", "d1");
731         assertMakeFile("d1/file1", 0644, "d1/file1");
732         assertMakeFile("d1/file2", 0644, "d1/file2");
733         assertMakeSymlink("d1/link1", "file1");
734         assertMakeSymlink("d1/linkX", "fileX");
735         assertMakeSymlink("link2", "d1/file2");
736         assertMakeSymlink("linkY", "d1/fileY");
737         assertChdir("..");
738
739         /* Note: this test uses archive_read_next_header()
740            instead of archive_read_next_header2() */
741         assert((a = archive_read_disk_new()) != NULL);
742         assertEqualIntA(a, ARCHIVE_OK,
743             archive_read_disk_set_symlink_logical(a));
744
745         /*
746          * Specified file is a symbolic link file.
747          */
748         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l/ld1"));
749         file_count = 5;
750
751         while (file_count--) {
752                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
753                 if (strcmp(archive_entry_pathname(ae), "l/ld1") == 0) {
754                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
755                 } else if (strcmp(archive_entry_pathname(ae),
756                     "l/ld1/file1") == 0) {
757                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
758                         assertEqualInt(archive_entry_size(ae), 8);
759                         assertEqualIntA(a, ARCHIVE_OK,
760                             archive_read_data_block(a, &p, &size, &offset));
761                         assertEqualInt((int)size, 8);
762                         assertEqualInt((int)offset, 0);
763                         assertEqualMem(p, "d1/file1", 8);
764                         assertEqualInt(ARCHIVE_EOF,
765                             archive_read_data_block(a, &p, &size, &offset));
766                         assertEqualInt((int)size, 0);
767                         assertEqualInt((int)offset, 8);
768                 } else if (strcmp(archive_entry_pathname(ae),
769                     "l/ld1/file2") == 0) {
770                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
771                         assertEqualInt(archive_entry_size(ae), 8);
772                         assertEqualIntA(a, ARCHIVE_OK,
773                             archive_read_data_block(a, &p, &size, &offset));
774                         assertEqualInt((int)size, 8);
775                         assertEqualInt((int)offset, 0);
776                         assertEqualMem(p, "d1/file2", 8);
777                         assertEqualInt(ARCHIVE_EOF,
778                             archive_read_data_block(a, &p, &size, &offset));
779                         assertEqualInt((int)size, 0);
780                         assertEqualInt((int)offset, 8);
781                 } else if (strcmp(archive_entry_pathname(ae),
782                     "l/ld1/link1") == 0) {
783                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
784                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
785                         assertEqualInt(archive_entry_size(ae), 8);
786                         assertEqualIntA(a, ARCHIVE_OK,
787                             archive_read_data_block(a, &p, &size, &offset));
788                         assertEqualInt((int)size, 8);
789                         assertEqualInt((int)offset, 0);
790                         assertEqualMem(p, "d1/file1", 8);
791                         assertEqualInt(ARCHIVE_EOF,
792                             archive_read_data_block(a, &p, &size, &offset));
793                         assertEqualInt((int)size, 0);
794                         assertEqualInt((int)offset, 8);
795                 } else if (strcmp(archive_entry_pathname(ae),
796                     "l/ld1/linkX") == 0) {
797                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
798                 }
799                 if (archive_entry_filetype(ae) == AE_IFDIR) {
800                         /* Descend into the current object */
801                         assertEqualIntA(a, ARCHIVE_OK,
802                             archive_read_disk_descend(a));
803                 }
804         }
805         /* There is no entry. */
806         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
807         /* Close the disk object. */
808         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
809
810         /*
811          * Specified file is a directory and it has symbolic files.
812          */
813         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l"));
814         file_count = 13;
815
816         while (file_count--) {
817                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
818                 if (strcmp(archive_entry_pathname(ae), "l") == 0) {
819                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
820                 } else if (strcmp(archive_entry_pathname(ae), "l/d1") == 0) {
821                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
822                 } else if (strcmp(archive_entry_pathname(ae),
823                     "l/d1/file1") == 0) {
824                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
825                         assertEqualInt(archive_entry_size(ae), 8);
826                         assertEqualIntA(a, ARCHIVE_OK,
827                             archive_read_data_block(a, &p, &size, &offset));
828                         assertEqualInt((int)size, 8);
829                         assertEqualInt((int)offset, 0);
830                         assertEqualMem(p, "d1/file1", 8);
831                         assertEqualInt(ARCHIVE_EOF,
832                             archive_read_data_block(a, &p, &size, &offset));
833                         assertEqualInt((int)size, 0);
834                         assertEqualInt((int)offset, 8);
835                 } else if (strcmp(archive_entry_pathname(ae),
836                     "l/d1/file2") == 0) {
837                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
838                         assertEqualInt(archive_entry_size(ae), 8);
839                         assertEqualIntA(a, ARCHIVE_OK,
840                             archive_read_data_block(a, &p, &size, &offset));
841                         assertEqualInt((int)size, 8);
842                         assertEqualInt((int)offset, 0);
843                         assertEqualMem(p, "d1/file2", 8);
844                         assertEqualInt(ARCHIVE_EOF,
845                             archive_read_data_block(a, &p, &size, &offset));
846                         assertEqualInt((int)size, 0);
847                         assertEqualInt((int)offset, 8);
848                 } else if (strcmp(archive_entry_pathname(ae),
849                     "l/d1/link1") == 0) {
850                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
851                         assertEqualInt(archive_entry_size(ae), 8);
852                         assertEqualIntA(a, ARCHIVE_OK,
853                             archive_read_data_block(a, &p, &size, &offset));
854                         assertEqualInt((int)size, 8);
855                         assertEqualInt((int)offset, 0);
856                         assertEqualMem(p, "d1/file1", 8);
857                         assertEqualInt(ARCHIVE_EOF,
858                             archive_read_data_block(a, &p, &size, &offset));
859                         assertEqualInt((int)size, 0);
860                         assertEqualInt((int)offset, 8);
861                 } else if (strcmp(archive_entry_pathname(ae),
862                     "l/d1/linkX") == 0) {
863                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
864                 } else if (strcmp(archive_entry_pathname(ae), "l/ld1") == 0) {
865                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
866                 } else if (strcmp(archive_entry_pathname(ae),
867                     "l/ld1/file1") == 0) {
868                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
869                         assertEqualInt(archive_entry_size(ae), 8);
870                         assertEqualIntA(a, ARCHIVE_OK,
871                             archive_read_data_block(a, &p, &size, &offset));
872                         assertEqualInt((int)size, 8);
873                         assertEqualInt((int)offset, 0);
874                         assertEqualMem(p, "d1/file1", 8);
875                         assertEqualInt(ARCHIVE_EOF,
876                             archive_read_data_block(a, &p, &size, &offset));
877                         assertEqualInt((int)size, 0);
878                         assertEqualInt((int)offset, 8);
879                 } else if (strcmp(archive_entry_pathname(ae),
880                     "l/ld1/file2") == 0) {
881                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
882                         assertEqualInt(archive_entry_size(ae), 8);
883                         assertEqualIntA(a, ARCHIVE_OK,
884                             archive_read_data_block(a, &p, &size, &offset));
885                         assertEqualInt((int)size, 8);
886                         assertEqualInt((int)offset, 0);
887                         assertEqualMem(p, "d1/file2", 8);
888                         assertEqualInt(ARCHIVE_EOF,
889                             archive_read_data_block(a, &p, &size, &offset));
890                         assertEqualInt((int)size, 0);
891                         assertEqualInt((int)offset, 8);
892                 } else if (strcmp(archive_entry_pathname(ae),
893                     "l/ld1/link1") == 0) {
894                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
895                         assertEqualInt(archive_entry_size(ae), 8);
896                         assertEqualIntA(a, ARCHIVE_OK,
897                             archive_read_data_block(a, &p, &size, &offset));
898                         assertEqualInt((int)size, 8);
899                         assertEqualInt((int)offset, 0);
900                         assertEqualMem(p, "d1/file1", 8);
901                         assertEqualInt(ARCHIVE_EOF,
902                             archive_read_data_block(a, &p, &size, &offset));
903                         assertEqualInt((int)size, 0);
904                         assertEqualInt((int)offset, 8);
905                 } else if (strcmp(archive_entry_pathname(ae),
906                     "l/ld1/linkX") == 0) {
907                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
908                 } else if (strcmp(archive_entry_pathname(ae),
909                     "l/link2") == 0) {
910                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
911                         assertEqualInt(archive_entry_size(ae), 8);
912                         assertEqualIntA(a, ARCHIVE_OK,
913                             archive_read_data_block(a, &p, &size, &offset));
914                         assertEqualInt((int)size, 8);
915                         assertEqualInt((int)offset, 0);
916                         assertEqualMem(p, "d1/file2", 8);
917                         assertEqualInt(ARCHIVE_EOF,
918                             archive_read_data_block(a, &p, &size, &offset));
919                         assertEqualInt((int)size, 0);
920                         assertEqualInt((int)offset, 8);
921                 } else if (strcmp(archive_entry_pathname(ae),
922                     "l/linkY") == 0) {
923                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
924                 }
925                 if (archive_entry_filetype(ae) == AE_IFDIR) {
926                         /* Descend into the current object */
927                         assertEqualIntA(a, ARCHIVE_OK,
928                             archive_read_disk_descend(a));
929                 }
930         }
931         /* There is no entry. */
932         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
933         /* Close the disk object. */
934         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
935         /* Destroy the disk object. */
936         assertEqualInt(ARCHIVE_OK, archive_read_free(a));
937 }
938
939 static void
940 test_symlink_logical_loop(void)
941 {
942         struct archive *a;
943         struct archive_entry *ae;
944         const void *p;
945         size_t size;
946         int64_t offset;
947         int file_count;
948
949         if (!canSymlink()) {
950                 skipping("Can't test symlinks on this filesystem");
951                 return;
952         }
953
954         /*
955          * Create a sample archive.
956          */
957         assertMakeDir("l2", 0755);
958         assertChdir("l2");
959         assertMakeDir("d1", 0755);
960         assertMakeDir("d1/d2", 0755);
961         assertMakeDir("d1/d2/d3", 0755);
962         assertMakeDir("d2", 0755);
963         assertMakeFile("d2/file1", 0644, "d2/file1");
964         assertMakeSymlink("d1/d2/ld1", "../../d1");
965         assertMakeSymlink("d1/d2/ld2", "../../d2");
966         assertChdir("..");
967
968         assert((ae = archive_entry_new()) != NULL);
969         assert((a = archive_read_disk_new()) != NULL);
970         assertEqualIntA(a, ARCHIVE_OK,
971             archive_read_disk_set_symlink_logical(a));
972
973         /*
974          * Specified file is a symbolic link file.
975          */
976         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l2/d1"));
977         file_count = 6;
978
979         while (file_count--) {
980                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
981                 if (strcmp(archive_entry_pathname(ae), "l2/d1") == 0) {
982                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
983                 } else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2") == 0) {
984                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
985                 } else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2/d3") == 0) {
986                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
987                 } else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2/ld1") == 0) {
988                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
989                 } else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2/ld2") == 0) {
990                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
991                 } else if (strcmp(archive_entry_pathname(ae),
992                     "l2/d1/d2/ld2/file1") == 0) {
993                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
994                         assertEqualInt(archive_entry_size(ae), 8);
995                         assertEqualIntA(a, ARCHIVE_OK,
996                             archive_read_data_block(a, &p, &size, &offset));
997                         assertEqualInt((int)size, 8);
998                         assertEqualInt((int)offset, 0);
999                         assertEqualMem(p, "d2/file1", 8);
1000                         assertEqualInt(ARCHIVE_EOF,
1001                             archive_read_data_block(a, &p, &size, &offset));
1002                         assertEqualInt((int)size, 0);
1003                         assertEqualInt((int)offset, 8);
1004                 }
1005                 if (archive_entry_filetype(ae) == AE_IFDIR) {
1006                         /* Descend into the current object */
1007                         assertEqualIntA(a, ARCHIVE_OK,
1008                             archive_read_disk_descend(a));
1009                 }
1010         }
1011         /* There is no entry. */
1012         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1013         /* Destroy the disk object. */
1014         assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1015         archive_entry_free(ae);
1016 }
1017
1018 static void
1019 test_restore_atime(void)
1020 {
1021         struct archive *a;
1022         struct archive_entry *ae;
1023         const void *p;
1024         size_t size;
1025         int64_t offset;
1026         int file_count;
1027
1028         if (!atimeIsUpdated()) {
1029                 skipping("Can't test restoring atime on this filesystem");
1030                 return;
1031         }
1032
1033         assertMakeDir("at", 0755);
1034         assertMakeFile("at/f1", 0644, "0123456789");
1035         assertMakeFile("at/f2", 0644, "hello world");
1036         assertMakeFile("at/fe", 0644, NULL);
1037         assertUtimes("at/f1", 886600, 0, 886600, 0);
1038         assertUtimes("at/f2", 886611, 0, 886611, 0);
1039         assertUtimes("at/fe", 886611, 0, 886611, 0);
1040         assertUtimes("at", 886622, 0, 886622, 0);
1041         file_count = 4;
1042
1043         assert((ae = archive_entry_new()) != NULL);
1044         assert((a = archive_read_disk_new()) != NULL);
1045
1046         /*
1047          * Test1: Traversals without archive_read_disk_set_atime_restored().
1048          */
1049         failure("Directory traversals should work as well");
1050         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1051         while (file_count--) {
1052                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1053                 if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1054                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1055                 } else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1056                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1057                         assertEqualInt(archive_entry_size(ae), 10);
1058                         assertEqualIntA(a, ARCHIVE_OK,
1059                             archive_read_data_block(a, &p, &size, &offset));
1060                         assertEqualInt((int)size, 10);
1061                         assertEqualInt((int)offset, 0);
1062                         assertEqualMem(p, "0123456789", 10);
1063                         assertEqualInt(ARCHIVE_EOF,
1064                             archive_read_data_block(a, &p, &size, &offset));
1065                         assertEqualInt((int)size, 0);
1066                         assertEqualInt((int)offset, 10);
1067                 } else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1068                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1069                         assertEqualInt(archive_entry_size(ae), 11);
1070                         assertEqualIntA(a, ARCHIVE_OK,
1071                             archive_read_data_block(a, &p, &size, &offset));
1072                         assertEqualInt((int)size, 11);
1073                         assertEqualInt((int)offset, 0);
1074                         assertEqualMem(p, "hello world", 11);
1075                         assertEqualInt(ARCHIVE_EOF,
1076                             archive_read_data_block(a, &p, &size, &offset));
1077                         assertEqualInt((int)size, 0);
1078                         assertEqualInt((int)offset, 11);
1079                 } else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1080                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1081                         assertEqualInt(archive_entry_size(ae), 0);
1082                 }
1083                 if (archive_entry_filetype(ae) == AE_IFDIR) {
1084                         /* Descend into the current object */
1085                         assertEqualIntA(a, ARCHIVE_OK,
1086                             archive_read_disk_descend(a));
1087                 }
1088         }
1089         /* There is no entry. */
1090         failure("There must be no entry");
1091         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1092
1093         /* On FreeBSD (and likely other systems), atime on
1094            dirs does not change when it is read. */
1095         /* failure("Atime should be restored"); */
1096         /* assertFileAtimeRecent("at"); */
1097         failure("Atime should be restored");
1098         assertFileAtimeRecent("at/f1");
1099         failure("Atime should be restored");
1100         assertFileAtimeRecent("at/f2");
1101         failure("The atime of a empty file should not be changed");
1102         assertFileAtime("at/fe", 886611, 0);
1103
1104         /* Close the disk object. */
1105         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1106
1107         /*
1108          * Test2: Traversals with archive_read_disk_set_atime_restored().
1109          */
1110         assertUtimes("at/f1", 886600, 0, 886600, 0);
1111         assertUtimes("at/f2", 886611, 0, 886611, 0);
1112         assertUtimes("at/fe", 886611, 0, 886611, 0);
1113         assertUtimes("at", 886622, 0, 886622, 0);
1114         file_count = 4;
1115         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a));
1116         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1117
1118         failure("Directory traversals should work as well");
1119         while (file_count--) {
1120                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1121                 if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1122                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1123                 } else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1124                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1125                         assertEqualInt(archive_entry_size(ae), 10);
1126                         assertEqualIntA(a, ARCHIVE_OK,
1127                             archive_read_data_block(a, &p, &size, &offset));
1128                         assertEqualInt((int)size, 10);
1129                         assertEqualInt((int)offset, 0);
1130                         assertEqualMem(p, "0123456789", 10);
1131                         assertEqualInt(ARCHIVE_EOF,
1132                             archive_read_data_block(a, &p, &size, &offset));
1133                         assertEqualInt((int)size, 0);
1134                         assertEqualInt((int)offset, 10);
1135                 } else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1136                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1137                         assertEqualInt(archive_entry_size(ae), 11);
1138                         assertEqualIntA(a, ARCHIVE_OK,
1139                             archive_read_data_block(a, &p, &size, &offset));
1140                         assertEqualInt((int)size, 11);
1141                         assertEqualInt((int)offset, 0);
1142                         assertEqualMem(p, "hello world", 11);
1143                         assertEqualInt(ARCHIVE_EOF,
1144                             archive_read_data_block(a, &p, &size, &offset));
1145                         assertEqualInt((int)size, 0);
1146                         assertEqualInt((int)offset, 11);
1147                 } else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1148                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1149                         assertEqualInt(archive_entry_size(ae), 0);
1150                 }
1151                 if (archive_entry_filetype(ae) == AE_IFDIR) {
1152                         /* Descend into the current object */
1153                         assertEqualIntA(a, ARCHIVE_OK,
1154                             archive_read_disk_descend(a));
1155                 }
1156         }
1157         /* There is no entry. */
1158         failure("There must be no entry");
1159         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1160
1161         failure("Atime should be restored");
1162         assertFileAtime("at", 886622, 0);
1163         failure("Atime should be restored");
1164         assertFileAtime("at/f1", 886600, 0);
1165         failure("Atime should be restored");
1166         assertFileAtime("at/f2", 886611, 0);
1167         failure("The atime of a empty file should not be changed");
1168         assertFileAtime("at/fe", 886611, 0);
1169
1170         /* Close the disk object. */
1171         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1172
1173         /*
1174          * Test3: Traversals with archive_read_disk_set_atime_restored() but
1175          * no data read as a listing.
1176          */
1177         assertUtimes("at/f1", 886600, 0, 886600, 0);
1178         assertUtimes("at/f2", 886611, 0, 886611, 0);
1179         assertUtimes("at/fe", 886611, 0, 886611, 0);
1180         assertUtimes("at", 886622, 0, 886622, 0);
1181         file_count = 4;
1182         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a));
1183         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1184
1185         failure("Directory traversals should work as well");
1186         while (file_count--) {
1187                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1188                 if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1189                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1190                 } else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1191                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1192                         assertEqualInt(archive_entry_size(ae), 10);
1193                 } else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1194                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1195                         assertEqualInt(archive_entry_size(ae), 11);
1196                 } else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1197                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1198                         assertEqualInt(archive_entry_size(ae), 0);
1199                 }
1200                 if (archive_entry_filetype(ae) == AE_IFDIR) {
1201                         /* Descend into the current object */
1202                         assertEqualIntA(a, ARCHIVE_OK,
1203                             archive_read_disk_descend(a));
1204                 }
1205         }
1206         /* There is no entry. */
1207         failure("There must be no entry");
1208         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1209
1210         failure("Atime should be restored");
1211         assertFileAtime("at", 886622, 0);
1212         failure("Atime should be restored");
1213         assertFileAtime("at/f1", 886600, 0);
1214         failure("Atime should be restored");
1215         assertFileAtime("at/f2", 886611, 0);
1216         failure("The atime of a empty file should not be changed");
1217         assertFileAtime("at/fe", 886611, 0);
1218
1219         if (!canNodump()) {
1220                 /* Destroy the disk object. */
1221                 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1222                 archive_entry_free(ae);
1223                 skipping("Can't test atime with nodump on this filesystem");
1224                 return;
1225         }
1226
1227         /* Close the disk object. */
1228         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1229
1230         /*
1231          * Test4: Traversals with archive_read_disk_set_atime_restored() and
1232          * archive_read_disk_honor_nodump().
1233          */
1234         assertNodump("at/f1");
1235         assertNodump("at/f2");
1236         assertUtimes("at/f1", 886600, 0, 886600, 0);
1237         assertUtimes("at/f2", 886611, 0, 886611, 0);
1238         assertUtimes("at/fe", 886611, 0, 886611, 0);
1239         assertUtimes("at", 886622, 0, 886622, 0);
1240         file_count = 2;
1241         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a,
1242                 ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP));
1243         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1244
1245         failure("Directory traversals should work as well");
1246         while (file_count--) {
1247                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1248                 if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1249                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1250                 } else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1251                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1252                         assertEqualInt(archive_entry_size(ae), 0);
1253                 }
1254                 if (archive_entry_filetype(ae) == AE_IFDIR) {
1255                         /* Descend into the current object */
1256                         assertEqualIntA(a, ARCHIVE_OK,
1257                             archive_read_disk_descend(a));
1258                 }
1259         }
1260         /* There is no entry. */
1261         failure("There must be no entry");
1262         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1263
1264         failure("Atime should be restored");
1265         assertFileAtime("at", 886622, 0);
1266         failure("Atime should be restored");
1267         assertFileAtime("at/f1", 886600, 0);
1268         failure("Atime should be restored");
1269         assertFileAtime("at/f2", 886611, 0);
1270         failure("The atime of a empty file should not be changed");
1271         assertFileAtime("at/fe", 886611, 0);
1272
1273         /* Destroy the disk object. */
1274         assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1275         archive_entry_free(ae);
1276 }
1277
1278 static int
1279 metadata_filter(struct archive *a, void *data, struct archive_entry *ae)
1280 {
1281         (void)data; /* UNUSED */
1282
1283         failure("CTime should be set");
1284         assertEqualInt(8, archive_entry_ctime_is_set(ae));
1285         failure("MTime should be set");
1286         assertEqualInt(16, archive_entry_mtime_is_set(ae));
1287
1288         if (archive_entry_mtime(ae) < 886611)
1289                 return (0);
1290         if (archive_read_disk_can_descend(a)) {
1291                 /* Descend into the current object */
1292                 failure("archive_read_disk_can_descend should work"
1293                         " in metadata filter");
1294                 assertEqualIntA(a, 1, archive_read_disk_can_descend(a));
1295                 failure("archive_read_disk_descend should work"
1296                         " in metadata filter");
1297                 assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a));
1298         }
1299         return (1);
1300 }
1301
1302 static void
1303 test_callbacks(void)
1304 {
1305         struct archive *a;
1306         struct archive *m;
1307         struct archive_entry *ae;
1308         const void *p;
1309         size_t size;
1310         int64_t offset;
1311         int file_count;
1312
1313         assertMakeDir("cb", 0755);
1314         assertMakeFile("cb/f1", 0644, "0123456789");
1315         assertMakeFile("cb/f2", 0644, "hello world");
1316         assertMakeFile("cb/fe", 0644, NULL);
1317         assertUtimes("cb/f1", 886600, 0, 886600, 0);
1318         assertUtimes("cb/f2", 886611, 0, 886611, 0);
1319         assertUtimes("cb/fe", 886611, 0, 886611, 0);
1320         assertUtimes("cb", 886622, 0, 886622, 0);
1321
1322         assert((ae = archive_entry_new()) != NULL);
1323         if (assert((a = archive_read_disk_new()) != NULL)) {
1324                 archive_entry_free(ae);
1325                 return;
1326         }
1327         if (assert((m = archive_match_new()) != NULL)) {
1328                 archive_entry_free(ae);
1329                 archive_read_free(a);
1330                 archive_match_free(m);
1331                 return;
1332         }
1333
1334         /*
1335          * Test1: Traversals with a name filter.
1336          */
1337         file_count = 3;
1338         assertEqualIntA(m, ARCHIVE_OK,
1339             archive_match_exclude_pattern(m, "cb/f2"));
1340         assertEqualIntA(a, ARCHIVE_OK,
1341             archive_read_disk_set_matching(a, m, NULL, NULL));
1342         failure("Directory traversals should work as well");
1343         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
1344         while (file_count--) {
1345                 archive_entry_clear(ae);
1346                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1347                 failure("File 'cb/f2' should be exclueded");
1348                 assert(strcmp(archive_entry_pathname(ae), "cb/f2") != 0);
1349                 if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
1350                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1351                 } else if (strcmp(archive_entry_pathname(ae), "cb/f1") == 0) {
1352                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1353                         assertEqualInt(archive_entry_size(ae), 10);
1354                         assertEqualIntA(a, ARCHIVE_OK,
1355                             archive_read_data_block(a, &p, &size, &offset));
1356                         assertEqualInt((int)size, 10);
1357                         assertEqualInt((int)offset, 0);
1358                         assertEqualMem(p, "0123456789", 10);
1359                         assertEqualInt(ARCHIVE_EOF,
1360                             archive_read_data_block(a, &p, &size, &offset));
1361                         assertEqualInt((int)size, 0);
1362                         assertEqualInt((int)offset, 10);
1363                 } else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
1364                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1365                         assertEqualInt(archive_entry_size(ae), 0);
1366                 }
1367                 if (archive_read_disk_can_descend(a)) {
1368                         /* Descend into the current object */
1369                         assertEqualIntA(a, ARCHIVE_OK,
1370                             archive_read_disk_descend(a));
1371                 }
1372         }
1373         /* There is no entry. */
1374         failure("There should be no entry");
1375         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1376
1377         /* Close the disk object. */
1378         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1379
1380         /*
1381          * Test2: Traversals with a metadata filter.
1382          */
1383         assertUtimes("cb/f1", 886600, 0, 886600, 0);
1384         assertUtimes("cb/f2", 886611, 0, 886611, 0);
1385         assertUtimes("cb/fe", 886611, 0, 886611, 0);
1386         assertUtimes("cb", 886622, 0, 886622, 0);
1387         file_count = 3;
1388         assertEqualIntA(a, ARCHIVE_OK,
1389             archive_read_disk_set_metadata_filter_callback(a, metadata_filter,
1390                     NULL));
1391         failure("Directory traversals should work as well");
1392         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
1393
1394         while (file_count--) {
1395                 archive_entry_clear(ae);
1396                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1397                 failure("File 'cb/f1' should be exclueded");
1398                 assert(strcmp(archive_entry_pathname(ae), "cb/f1") != 0);
1399                 if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
1400                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1401                 } else if (strcmp(archive_entry_pathname(ae), "cb/f2") == 0) {
1402                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1403                         assertEqualInt(archive_entry_size(ae), 11);
1404                         assertEqualIntA(a, ARCHIVE_OK,
1405                             archive_read_data_block(a, &p, &size, &offset));
1406                         assertEqualInt((int)size, 11);
1407                         assertEqualInt((int)offset, 0);
1408                         assertEqualMem(p, "hello world", 11);
1409                         assertEqualInt(ARCHIVE_EOF,
1410                             archive_read_data_block(a, &p, &size, &offset));
1411                         assertEqualInt((int)size, 0);
1412                         assertEqualInt((int)offset, 11);
1413                 } else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
1414                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1415                         assertEqualInt(archive_entry_size(ae), 0);
1416                 }
1417         }
1418         /* There is no entry. */
1419         failure("There should be no entry");
1420         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1421
1422         /* Destroy the disk object. */
1423         assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1424         assertEqualInt(ARCHIVE_OK, archive_match_free(m));
1425         archive_entry_free(ae);
1426 }
1427
1428 static void
1429 test_nodump(void)
1430 {
1431         struct archive *a;
1432         struct archive_entry *ae;
1433         const void *p;
1434         size_t size;
1435         int64_t offset;
1436         int file_count;
1437
1438         if (!canNodump()) {
1439                 skipping("Can't test nodump on this filesystem");
1440                 return;
1441         }
1442
1443         assertMakeDir("nd", 0755);
1444         assertMakeFile("nd/f1", 0644, "0123456789");
1445         assertMakeFile("nd/f2", 0644, "hello world");
1446         assertMakeFile("nd/fe", 0644, NULL);
1447         assertNodump("nd/f2");
1448         assertUtimes("nd/f1", 886600, 0, 886600, 0);
1449         assertUtimes("nd/f2", 886611, 0, 886611, 0);
1450         assertUtimes("nd/fe", 886611, 0, 886611, 0);
1451         assertUtimes("nd", 886622, 0, 886622, 0);
1452
1453         assert((ae = archive_entry_new()) != NULL);
1454         assert((a = archive_read_disk_new()) != NULL);
1455
1456         /*
1457          * Test1: Traversals without archive_read_disk_honor_nodump().
1458          */
1459         failure("Directory traversals should work as well");
1460         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
1461
1462         file_count = 4;
1463         while (file_count--) {
1464                 archive_entry_clear(ae);
1465                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1466                 if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
1467                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1468                 } else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) {
1469                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1470                         assertEqualInt(archive_entry_size(ae), 10);
1471                         assertEqualIntA(a, ARCHIVE_OK,
1472                             archive_read_data_block(a, &p, &size, &offset));
1473                         assertEqualInt((int)size, 10);
1474                         assertEqualInt((int)offset, 0);
1475                         assertEqualMem(p, "0123456789", 10);
1476                         assertEqualInt(ARCHIVE_EOF,
1477                             archive_read_data_block(a, &p, &size, &offset));
1478                         assertEqualInt((int)size, 0);
1479                         assertEqualInt((int)offset, 10);
1480                 } else if (strcmp(archive_entry_pathname(ae), "nd/f2") == 0) {
1481                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1482                         assertEqualInt(archive_entry_size(ae), 11);
1483                         assertEqualIntA(a, ARCHIVE_OK,
1484                             archive_read_data_block(a, &p, &size, &offset));
1485                         assertEqualInt((int)size, 11);
1486                         assertEqualInt((int)offset, 0);
1487                         assertEqualMem(p, "hello world", 11);
1488                         assertEqualInt(ARCHIVE_EOF,
1489                             archive_read_data_block(a, &p, &size, &offset));
1490                         assertEqualInt((int)size, 0);
1491                         assertEqualInt((int)offset, 11);
1492                 } else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
1493                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1494                         assertEqualInt(archive_entry_size(ae), 0);
1495                 }
1496                 if (archive_read_disk_can_descend(a)) {
1497                         /* Descend into the current object */
1498                         assertEqualIntA(a, ARCHIVE_OK,
1499                             archive_read_disk_descend(a));
1500                 }
1501         }
1502         /* There is no entry. */
1503         failure("There should be no entry");
1504         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1505
1506         /* Close the disk object. */
1507         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1508
1509         /*
1510          * Test2: Traversals with archive_read_disk_honor_nodump().
1511          */
1512         assertUtimes("nd/f1", 886600, 0, 886600, 0);
1513         assertUtimes("nd/f2", 886611, 0, 886611, 0);
1514         assertUtimes("nd/fe", 886611, 0, 886611, 0);
1515         assertUtimes("nd", 886622, 0, 886622, 0);
1516
1517         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a,
1518                 ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP));
1519         failure("Directory traversals should work as well");
1520         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
1521
1522         file_count = 3;
1523         while (file_count--) {
1524                 archive_entry_clear(ae);
1525                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1526                 failure("File 'nd/f2' should be exclueded");
1527                 assert(strcmp(archive_entry_pathname(ae), "nd/f2") != 0);
1528                 if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
1529                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1530                 } else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) {
1531                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1532                         assertEqualInt(archive_entry_size(ae), 10);
1533                         assertEqualIntA(a, ARCHIVE_OK,
1534                             archive_read_data_block(a, &p, &size, &offset));
1535                         assertEqualInt((int)size, 10);
1536                         assertEqualInt((int)offset, 0);
1537                         assertEqualMem(p, "0123456789", 10);
1538                         assertEqualInt(ARCHIVE_EOF,
1539                             archive_read_data_block(a, &p, &size, &offset));
1540                         assertEqualInt((int)size, 0);
1541                         assertEqualInt((int)offset, 10);
1542                 } else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
1543                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1544                         assertEqualInt(archive_entry_size(ae), 0);
1545                 }
1546                 if (archive_read_disk_can_descend(a)) {
1547                         /* Descend into the current object */
1548                         assertEqualIntA(a, ARCHIVE_OK,
1549                             archive_read_disk_descend(a));
1550                 }
1551         }
1552         /* There is no entry. */
1553         failure("There should be no entry");
1554         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1555
1556         failure("Atime should be restored");
1557         assertFileAtime("nd/f2", 886611, 0);
1558
1559         /* Destroy the disk object. */
1560         assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1561         archive_entry_free(ae);
1562 }
1563
1564 DEFINE_TEST(test_read_disk_directory_traversals)
1565 {
1566         /* Basic test. */
1567         test_basic();
1568         /* Test hybird mode; follow symlink initially, then not. */
1569         test_symlink_hybrid();
1570         /* Test logcal mode; follow all symlinks. */
1571         test_symlink_logical();
1572         /* Test logcal mode; prevent loop in symlinks. */ 
1573         test_symlink_logical_loop();
1574         /* Test to restore atime. */
1575         test_restore_atime();
1576         /* Test callbacks. */
1577         test_callbacks();
1578         /* Test nodump. */
1579         test_nodump();
1580 }