]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/libarchive/libarchive/test/test_read_disk_directory_traversals.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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         assert((ae = archive_entry_new()) != NULL);
740         assert((a = archive_read_disk_new()) != NULL);
741         assertEqualIntA(a, ARCHIVE_OK,
742             archive_read_disk_set_symlink_logical(a));
743
744         /*
745          * Specified file is a symbolic link file.
746          */
747         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l/ld1"));
748         file_count = 5;
749
750         while (file_count--) {
751                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
752                 if (strcmp(archive_entry_pathname(ae), "l/ld1") == 0) {
753                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
754                 } else if (strcmp(archive_entry_pathname(ae),
755                     "l/ld1/file1") == 0) {
756                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
757                         assertEqualInt(archive_entry_size(ae), 8);
758                         assertEqualIntA(a, ARCHIVE_OK,
759                             archive_read_data_block(a, &p, &size, &offset));
760                         assertEqualInt((int)size, 8);
761                         assertEqualInt((int)offset, 0);
762                         assertEqualMem(p, "d1/file1", 8);
763                         assertEqualInt(ARCHIVE_EOF,
764                             archive_read_data_block(a, &p, &size, &offset));
765                         assertEqualInt((int)size, 0);
766                         assertEqualInt((int)offset, 8);
767                 } else if (strcmp(archive_entry_pathname(ae),
768                     "l/ld1/file2") == 0) {
769                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
770                         assertEqualInt(archive_entry_size(ae), 8);
771                         assertEqualIntA(a, ARCHIVE_OK,
772                             archive_read_data_block(a, &p, &size, &offset));
773                         assertEqualInt((int)size, 8);
774                         assertEqualInt((int)offset, 0);
775                         assertEqualMem(p, "d1/file2", 8);
776                         assertEqualInt(ARCHIVE_EOF,
777                             archive_read_data_block(a, &p, &size, &offset));
778                         assertEqualInt((int)size, 0);
779                         assertEqualInt((int)offset, 8);
780                 } else if (strcmp(archive_entry_pathname(ae),
781                     "l/ld1/link1") == 0) {
782                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
783                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
784                         assertEqualInt(archive_entry_size(ae), 8);
785                         assertEqualIntA(a, ARCHIVE_OK,
786                             archive_read_data_block(a, &p, &size, &offset));
787                         assertEqualInt((int)size, 8);
788                         assertEqualInt((int)offset, 0);
789                         assertEqualMem(p, "d1/file1", 8);
790                         assertEqualInt(ARCHIVE_EOF,
791                             archive_read_data_block(a, &p, &size, &offset));
792                         assertEqualInt((int)size, 0);
793                         assertEqualInt((int)offset, 8);
794                 } else if (strcmp(archive_entry_pathname(ae),
795                     "l/ld1/linkX") == 0) {
796                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
797                 }
798                 if (archive_entry_filetype(ae) == AE_IFDIR) {
799                         /* Descend into the current object */
800                         assertEqualIntA(a, ARCHIVE_OK,
801                             archive_read_disk_descend(a));
802                 }
803         }
804         /* There is no entry. */
805         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
806         /* Close the disk object. */
807         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
808
809         /*
810          * Specified file is a directory and it has symbolic files.
811          */
812         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l"));
813         file_count = 13;
814
815         while (file_count--) {
816                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
817                 if (strcmp(archive_entry_pathname(ae), "l") == 0) {
818                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
819                 } else if (strcmp(archive_entry_pathname(ae), "l/d1") == 0) {
820                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
821                 } else if (strcmp(archive_entry_pathname(ae),
822                     "l/d1/file1") == 0) {
823                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
824                         assertEqualInt(archive_entry_size(ae), 8);
825                         assertEqualIntA(a, ARCHIVE_OK,
826                             archive_read_data_block(a, &p, &size, &offset));
827                         assertEqualInt((int)size, 8);
828                         assertEqualInt((int)offset, 0);
829                         assertEqualMem(p, "d1/file1", 8);
830                         assertEqualInt(ARCHIVE_EOF,
831                             archive_read_data_block(a, &p, &size, &offset));
832                         assertEqualInt((int)size, 0);
833                         assertEqualInt((int)offset, 8);
834                 } else if (strcmp(archive_entry_pathname(ae),
835                     "l/d1/file2") == 0) {
836                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
837                         assertEqualInt(archive_entry_size(ae), 8);
838                         assertEqualIntA(a, ARCHIVE_OK,
839                             archive_read_data_block(a, &p, &size, &offset));
840                         assertEqualInt((int)size, 8);
841                         assertEqualInt((int)offset, 0);
842                         assertEqualMem(p, "d1/file2", 8);
843                         assertEqualInt(ARCHIVE_EOF,
844                             archive_read_data_block(a, &p, &size, &offset));
845                         assertEqualInt((int)size, 0);
846                         assertEqualInt((int)offset, 8);
847                 } else if (strcmp(archive_entry_pathname(ae),
848                     "l/d1/link1") == 0) {
849                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
850                         assertEqualInt(archive_entry_size(ae), 8);
851                         assertEqualIntA(a, ARCHIVE_OK,
852                             archive_read_data_block(a, &p, &size, &offset));
853                         assertEqualInt((int)size, 8);
854                         assertEqualInt((int)offset, 0);
855                         assertEqualMem(p, "d1/file1", 8);
856                         assertEqualInt(ARCHIVE_EOF,
857                             archive_read_data_block(a, &p, &size, &offset));
858                         assertEqualInt((int)size, 0);
859                         assertEqualInt((int)offset, 8);
860                 } else if (strcmp(archive_entry_pathname(ae),
861                     "l/d1/linkX") == 0) {
862                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
863                 } else if (strcmp(archive_entry_pathname(ae), "l/ld1") == 0) {
864                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
865                 } else if (strcmp(archive_entry_pathname(ae),
866                     "l/ld1/file1") == 0) {
867                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
868                         assertEqualInt(archive_entry_size(ae), 8);
869                         assertEqualIntA(a, ARCHIVE_OK,
870                             archive_read_data_block(a, &p, &size, &offset));
871                         assertEqualInt((int)size, 8);
872                         assertEqualInt((int)offset, 0);
873                         assertEqualMem(p, "d1/file1", 8);
874                         assertEqualInt(ARCHIVE_EOF,
875                             archive_read_data_block(a, &p, &size, &offset));
876                         assertEqualInt((int)size, 0);
877                         assertEqualInt((int)offset, 8);
878                 } else if (strcmp(archive_entry_pathname(ae),
879                     "l/ld1/file2") == 0) {
880                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
881                         assertEqualInt(archive_entry_size(ae), 8);
882                         assertEqualIntA(a, ARCHIVE_OK,
883                             archive_read_data_block(a, &p, &size, &offset));
884                         assertEqualInt((int)size, 8);
885                         assertEqualInt((int)offset, 0);
886                         assertEqualMem(p, "d1/file2", 8);
887                         assertEqualInt(ARCHIVE_EOF,
888                             archive_read_data_block(a, &p, &size, &offset));
889                         assertEqualInt((int)size, 0);
890                         assertEqualInt((int)offset, 8);
891                 } else if (strcmp(archive_entry_pathname(ae),
892                     "l/ld1/link1") == 0) {
893                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
894                         assertEqualInt(archive_entry_size(ae), 8);
895                         assertEqualIntA(a, ARCHIVE_OK,
896                             archive_read_data_block(a, &p, &size, &offset));
897                         assertEqualInt((int)size, 8);
898                         assertEqualInt((int)offset, 0);
899                         assertEqualMem(p, "d1/file1", 8);
900                         assertEqualInt(ARCHIVE_EOF,
901                             archive_read_data_block(a, &p, &size, &offset));
902                         assertEqualInt((int)size, 0);
903                         assertEqualInt((int)offset, 8);
904                 } else if (strcmp(archive_entry_pathname(ae),
905                     "l/ld1/linkX") == 0) {
906                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
907                 } else if (strcmp(archive_entry_pathname(ae),
908                     "l/link2") == 0) {
909                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
910                         assertEqualInt(archive_entry_size(ae), 8);
911                         assertEqualIntA(a, ARCHIVE_OK,
912                             archive_read_data_block(a, &p, &size, &offset));
913                         assertEqualInt((int)size, 8);
914                         assertEqualInt((int)offset, 0);
915                         assertEqualMem(p, "d1/file2", 8);
916                         assertEqualInt(ARCHIVE_EOF,
917                             archive_read_data_block(a, &p, &size, &offset));
918                         assertEqualInt((int)size, 0);
919                         assertEqualInt((int)offset, 8);
920                 } else if (strcmp(archive_entry_pathname(ae),
921                     "l/linkY") == 0) {
922                         assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
923                 }
924                 if (archive_entry_filetype(ae) == AE_IFDIR) {
925                         /* Descend into the current object */
926                         assertEqualIntA(a, ARCHIVE_OK,
927                             archive_read_disk_descend(a));
928                 }
929         }
930         /* There is no entry. */
931         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
932         /* Close the disk object. */
933         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
934         /* Destroy the disk object. */
935         assertEqualInt(ARCHIVE_OK, archive_read_free(a));
936         archive_entry_free(ae);
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         failure("Atime should be restored");
1094         assertFileAtimeRecent("at");
1095         failure("Atime should be restored");
1096         assertFileAtimeRecent("at/f1");
1097         failure("Atime should be restored");
1098         assertFileAtimeRecent("at/f2");
1099         failure("The atime of a empty file should not be changed");
1100         assertFileAtime("at/fe", 886611, 0);
1101
1102         /* Close the disk object. */
1103         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1104
1105         /*
1106          * Test2: Traversals with archive_read_disk_set_atime_restored().
1107          */
1108         assertUtimes("at/f1", 886600, 0, 886600, 0);
1109         assertUtimes("at/f2", 886611, 0, 886611, 0);
1110         assertUtimes("at/fe", 886611, 0, 886611, 0);
1111         assertUtimes("at", 886622, 0, 886622, 0);
1112         file_count = 4;
1113         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a));
1114         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1115
1116         failure("Directory traversals should work as well");
1117         while (file_count--) {
1118                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1119                 if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1120                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1121                 } else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1122                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1123                         assertEqualInt(archive_entry_size(ae), 10);
1124                         assertEqualIntA(a, ARCHIVE_OK,
1125                             archive_read_data_block(a, &p, &size, &offset));
1126                         assertEqualInt((int)size, 10);
1127                         assertEqualInt((int)offset, 0);
1128                         assertEqualMem(p, "0123456789", 10);
1129                         assertEqualInt(ARCHIVE_EOF,
1130                             archive_read_data_block(a, &p, &size, &offset));
1131                         assertEqualInt((int)size, 0);
1132                         assertEqualInt((int)offset, 10);
1133                 } else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1134                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1135                         assertEqualInt(archive_entry_size(ae), 11);
1136                         assertEqualIntA(a, ARCHIVE_OK,
1137                             archive_read_data_block(a, &p, &size, &offset));
1138                         assertEqualInt((int)size, 11);
1139                         assertEqualInt((int)offset, 0);
1140                         assertEqualMem(p, "hello world", 11);
1141                         assertEqualInt(ARCHIVE_EOF,
1142                             archive_read_data_block(a, &p, &size, &offset));
1143                         assertEqualInt((int)size, 0);
1144                         assertEqualInt((int)offset, 11);
1145                 } else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1146                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1147                         assertEqualInt(archive_entry_size(ae), 0);
1148                 }
1149                 if (archive_entry_filetype(ae) == AE_IFDIR) {
1150                         /* Descend into the current object */
1151                         assertEqualIntA(a, ARCHIVE_OK,
1152                             archive_read_disk_descend(a));
1153                 }
1154         }
1155         /* There is no entry. */
1156         failure("There must be no entry");
1157         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1158
1159         failure("Atime should be restored");
1160         assertFileAtime("at", 886622, 0);
1161         failure("Atime should be restored");
1162         assertFileAtime("at/f1", 886600, 0);
1163         failure("Atime should be restored");
1164         assertFileAtime("at/f2", 886611, 0);
1165         failure("The atime of a empty file should not be changed");
1166         assertFileAtime("at/fe", 886611, 0);
1167
1168         /* Close the disk object. */
1169         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1170
1171         /*
1172          * Test3: Traversals with archive_read_disk_set_atime_restored() but
1173          * no data read as a listing.
1174          */
1175         assertUtimes("at/f1", 886600, 0, 886600, 0);
1176         assertUtimes("at/f2", 886611, 0, 886611, 0);
1177         assertUtimes("at/fe", 886611, 0, 886611, 0);
1178         assertUtimes("at", 886622, 0, 886622, 0);
1179         file_count = 4;
1180         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a));
1181         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1182
1183         failure("Directory traversals should work as well");
1184         while (file_count--) {
1185                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1186                 if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1187                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1188                 } else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1189                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1190                         assertEqualInt(archive_entry_size(ae), 10);
1191                 } else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1192                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1193                         assertEqualInt(archive_entry_size(ae), 11);
1194                 } else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1195                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1196                         assertEqualInt(archive_entry_size(ae), 0);
1197                 }
1198                 if (archive_entry_filetype(ae) == AE_IFDIR) {
1199                         /* Descend into the current object */
1200                         assertEqualIntA(a, ARCHIVE_OK,
1201                             archive_read_disk_descend(a));
1202                 }
1203         }
1204         /* There is no entry. */
1205         failure("There must be no entry");
1206         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1207
1208         failure("Atime should be restored");
1209         assertFileAtime("at", 886622, 0);
1210         failure("Atime should be restored");
1211         assertFileAtime("at/f1", 886600, 0);
1212         failure("Atime should be restored");
1213         assertFileAtime("at/f2", 886611, 0);
1214         failure("The atime of a empty file should not be changed");
1215         assertFileAtime("at/fe", 886611, 0);
1216
1217         if (!canNodump()) {
1218                 /* Destroy the disk object. */
1219                 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1220                 archive_entry_free(ae);
1221                 skipping("Can't test atime with nodump on this filesystem");
1222                 return;
1223         }
1224
1225         /* Close the disk object. */
1226         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1227
1228         /*
1229          * Test4: Traversals with archive_read_disk_set_atime_restored() and
1230          * archive_read_disk_honor_nodump().
1231          */
1232         assertNodump("at/f1");
1233         assertNodump("at/f2");
1234         assertUtimes("at/f1", 886600, 0, 886600, 0);
1235         assertUtimes("at/f2", 886611, 0, 886611, 0);
1236         assertUtimes("at/fe", 886611, 0, 886611, 0);
1237         assertUtimes("at", 886622, 0, 886622, 0);
1238         file_count = 2;
1239         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a,
1240                 ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP));
1241         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1242
1243         failure("Directory traversals should work as well");
1244         while (file_count--) {
1245                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1246                 if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1247                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1248                 } else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1249                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1250                         assertEqualInt(archive_entry_size(ae), 0);
1251                 }
1252                 if (archive_entry_filetype(ae) == AE_IFDIR) {
1253                         /* Descend into the current object */
1254                         assertEqualIntA(a, ARCHIVE_OK,
1255                             archive_read_disk_descend(a));
1256                 }
1257         }
1258         /* There is no entry. */
1259         failure("There must be no entry");
1260         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1261
1262         failure("Atime should be restored");
1263         assertFileAtime("at", 886622, 0);
1264         failure("Atime should be restored");
1265         assertFileAtime("at/f1", 886600, 0);
1266         failure("Atime should be restored");
1267         assertFileAtime("at/f2", 886611, 0);
1268         failure("The atime of a empty file should not be changed");
1269         assertFileAtime("at/fe", 886611, 0);
1270
1271         /* Destroy the disk object. */
1272         assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1273         archive_entry_free(ae);
1274 }
1275
1276 static int
1277 metadata_filter(struct archive *a, void *data, struct archive_entry *ae)
1278 {
1279         (void)data; /* UNUSED */
1280
1281         failure("CTime should be set");
1282         assertEqualInt(8, archive_entry_ctime_is_set(ae));
1283         failure("MTime should be set");
1284         assertEqualInt(16, archive_entry_mtime_is_set(ae));
1285
1286         if (archive_entry_mtime(ae) < 886611)
1287                 return (0);
1288         if (archive_read_disk_can_descend(a)) {
1289                 /* Descend into the current object */
1290                 failure("archive_read_disk_can_descend should work"
1291                         " in metadata filter");
1292                 assertEqualIntA(a, 1, archive_read_disk_can_descend(a));
1293                 failure("archive_read_disk_descend should work"
1294                         " in metadata filter");
1295                 assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a));
1296         }
1297         return (1);
1298 }
1299
1300 static void
1301 test_callbacks(void)
1302 {
1303         struct archive *a;
1304         struct archive *m;
1305         struct archive_entry *ae;
1306         const void *p;
1307         size_t size;
1308         int64_t offset;
1309         int file_count;
1310
1311         assertMakeDir("cb", 0755);
1312         assertMakeFile("cb/f1", 0644, "0123456789");
1313         assertMakeFile("cb/f2", 0644, "hello world");
1314         assertMakeFile("cb/fe", 0644, NULL);
1315         assertUtimes("cb/f1", 886600, 0, 886600, 0);
1316         assertUtimes("cb/f2", 886611, 0, 886611, 0);
1317         assertUtimes("cb/fe", 886611, 0, 886611, 0);
1318         assertUtimes("cb", 886622, 0, 886622, 0);
1319
1320         assert((ae = archive_entry_new()) != NULL);
1321         if (assert((a = archive_read_disk_new()) != NULL)) {
1322                 archive_entry_free(ae);
1323                 return;
1324         }
1325         if (assert((m = archive_match_new()) != NULL)) {
1326                 archive_entry_free(ae);
1327                 archive_read_free(a);
1328                 return;
1329         }
1330
1331         /*
1332          * Test1: Traversals with a name filter.
1333          */
1334         file_count = 3;
1335         assertEqualIntA(m, ARCHIVE_OK,
1336             archive_match_exclude_pattern(m, "cb/f2"));
1337         assertEqualIntA(a, ARCHIVE_OK,
1338             archive_read_disk_set_matching(a, m, NULL, NULL));
1339         failure("Directory traversals should work as well");
1340         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
1341         while (file_count--) {
1342                 archive_entry_clear(ae);
1343                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1344                 failure("File 'cb/f2' should be exclueded");
1345                 assert(strcmp(archive_entry_pathname(ae), "cb/f2") != 0);
1346                 if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
1347                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1348                 } else if (strcmp(archive_entry_pathname(ae), "cb/f1") == 0) {
1349                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1350                         assertEqualInt(archive_entry_size(ae), 10);
1351                         assertEqualIntA(a, ARCHIVE_OK,
1352                             archive_read_data_block(a, &p, &size, &offset));
1353                         assertEqualInt((int)size, 10);
1354                         assertEqualInt((int)offset, 0);
1355                         assertEqualMem(p, "0123456789", 10);
1356                         assertEqualInt(ARCHIVE_EOF,
1357                             archive_read_data_block(a, &p, &size, &offset));
1358                         assertEqualInt((int)size, 0);
1359                         assertEqualInt((int)offset, 10);
1360                 } else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
1361                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1362                         assertEqualInt(archive_entry_size(ae), 0);
1363                 }
1364                 if (archive_read_disk_can_descend(a)) {
1365                         /* Descend into the current object */
1366                         assertEqualIntA(a, ARCHIVE_OK,
1367                             archive_read_disk_descend(a));
1368                 }
1369         }
1370         /* There is no entry. */
1371         failure("There should be no entry");
1372         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1373
1374         /* Close the disk object. */
1375         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1376
1377         /*
1378          * Test2: Traversals with a metadata filter.
1379          */
1380         assertUtimes("cb/f1", 886600, 0, 886600, 0);
1381         assertUtimes("cb/f2", 886611, 0, 886611, 0);
1382         assertUtimes("cb/fe", 886611, 0, 886611, 0);
1383         assertUtimes("cb", 886622, 0, 886622, 0);
1384         file_count = 3;
1385         assertEqualIntA(a, ARCHIVE_OK,
1386             archive_read_disk_set_metadata_filter_callback(a, metadata_filter,
1387                     NULL));
1388         failure("Directory traversals should work as well");
1389         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
1390
1391         while (file_count--) {
1392                 archive_entry_clear(ae);
1393                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1394                 failure("File 'cb/f1' should be exclueded");
1395                 assert(strcmp(archive_entry_pathname(ae), "cb/f1") != 0);
1396                 if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
1397                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1398                 } else if (strcmp(archive_entry_pathname(ae), "cb/f2") == 0) {
1399                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1400                         assertEqualInt(archive_entry_size(ae), 11);
1401                         assertEqualIntA(a, ARCHIVE_OK,
1402                             archive_read_data_block(a, &p, &size, &offset));
1403                         assertEqualInt((int)size, 11);
1404                         assertEqualInt((int)offset, 0);
1405                         assertEqualMem(p, "hello world", 11);
1406                         assertEqualInt(ARCHIVE_EOF,
1407                             archive_read_data_block(a, &p, &size, &offset));
1408                         assertEqualInt((int)size, 0);
1409                         assertEqualInt((int)offset, 11);
1410                 } else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
1411                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1412                         assertEqualInt(archive_entry_size(ae), 0);
1413                 }
1414         }
1415         /* There is no entry. */
1416         failure("There should be no entry");
1417         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1418
1419         /* Destroy the disk object. */
1420         assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1421         assertEqualInt(ARCHIVE_OK, archive_match_free(m));
1422         archive_entry_free(ae);
1423 }
1424
1425 static void
1426 test_nodump(void)
1427 {
1428         struct archive *a;
1429         struct archive_entry *ae;
1430         const void *p;
1431         size_t size;
1432         int64_t offset;
1433         int file_count;
1434
1435         if (!canNodump()) {
1436                 skipping("Can't test nodump on this filesystem");
1437                 return;
1438         }
1439
1440         assertMakeDir("nd", 0755);
1441         assertMakeFile("nd/f1", 0644, "0123456789");
1442         assertMakeFile("nd/f2", 0644, "hello world");
1443         assertMakeFile("nd/fe", 0644, NULL);
1444         assertNodump("nd/f2");
1445         assertUtimes("nd/f1", 886600, 0, 886600, 0);
1446         assertUtimes("nd/f2", 886611, 0, 886611, 0);
1447         assertUtimes("nd/fe", 886611, 0, 886611, 0);
1448         assertUtimes("nd", 886622, 0, 886622, 0);
1449
1450         assert((ae = archive_entry_new()) != NULL);
1451         assert((a = archive_read_disk_new()) != NULL);
1452
1453         /*
1454          * Test1: Traversals without archive_read_disk_honor_nodump().
1455          */
1456         failure("Directory traversals should work as well");
1457         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
1458
1459         file_count = 4;
1460         while (file_count--) {
1461                 archive_entry_clear(ae);
1462                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1463                 if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
1464                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1465                 } else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) {
1466                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1467                         assertEqualInt(archive_entry_size(ae), 10);
1468                         assertEqualIntA(a, ARCHIVE_OK,
1469                             archive_read_data_block(a, &p, &size, &offset));
1470                         assertEqualInt((int)size, 10);
1471                         assertEqualInt((int)offset, 0);
1472                         assertEqualMem(p, "0123456789", 10);
1473                         assertEqualInt(ARCHIVE_EOF,
1474                             archive_read_data_block(a, &p, &size, &offset));
1475                         assertEqualInt((int)size, 0);
1476                         assertEqualInt((int)offset, 10);
1477                 } else if (strcmp(archive_entry_pathname(ae), "nd/f2") == 0) {
1478                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1479                         assertEqualInt(archive_entry_size(ae), 11);
1480                         assertEqualIntA(a, ARCHIVE_OK,
1481                             archive_read_data_block(a, &p, &size, &offset));
1482                         assertEqualInt((int)size, 11);
1483                         assertEqualInt((int)offset, 0);
1484                         assertEqualMem(p, "hello world", 11);
1485                         assertEqualInt(ARCHIVE_EOF,
1486                             archive_read_data_block(a, &p, &size, &offset));
1487                         assertEqualInt((int)size, 0);
1488                         assertEqualInt((int)offset, 11);
1489                 } else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
1490                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1491                         assertEqualInt(archive_entry_size(ae), 0);
1492                 }
1493                 if (archive_read_disk_can_descend(a)) {
1494                         /* Descend into the current object */
1495                         assertEqualIntA(a, ARCHIVE_OK,
1496                             archive_read_disk_descend(a));
1497                 }
1498         }
1499         /* There is no entry. */
1500         failure("There should be no entry");
1501         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1502
1503         /* Close the disk object. */
1504         assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1505
1506         /*
1507          * Test2: Traversals with archive_read_disk_honor_nodump().
1508          */
1509         assertUtimes("nd/f1", 886600, 0, 886600, 0);
1510         assertUtimes("nd/f2", 886611, 0, 886611, 0);
1511         assertUtimes("nd/fe", 886611, 0, 886611, 0);
1512         assertUtimes("nd", 886622, 0, 886622, 0);
1513
1514         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a,
1515                 ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP));
1516         failure("Directory traversals should work as well");
1517         assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
1518
1519         file_count = 3;
1520         while (file_count--) {
1521                 archive_entry_clear(ae);
1522                 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1523                 failure("File 'nd/f2' should be exclueded");
1524                 assert(strcmp(archive_entry_pathname(ae), "nd/f2") != 0);
1525                 if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
1526                         assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1527                 } else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) {
1528                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1529                         assertEqualInt(archive_entry_size(ae), 10);
1530                         assertEqualIntA(a, ARCHIVE_OK,
1531                             archive_read_data_block(a, &p, &size, &offset));
1532                         assertEqualInt((int)size, 10);
1533                         assertEqualInt((int)offset, 0);
1534                         assertEqualMem(p, "0123456789", 10);
1535                         assertEqualInt(ARCHIVE_EOF,
1536                             archive_read_data_block(a, &p, &size, &offset));
1537                         assertEqualInt((int)size, 0);
1538                         assertEqualInt((int)offset, 10);
1539                 } else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
1540                         assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1541                         assertEqualInt(archive_entry_size(ae), 0);
1542                 }
1543                 if (archive_read_disk_can_descend(a)) {
1544                         /* Descend into the current object */
1545                         assertEqualIntA(a, ARCHIVE_OK,
1546                             archive_read_disk_descend(a));
1547                 }
1548         }
1549         /* There is no entry. */
1550         failure("There should be no entry");
1551         assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1552
1553         failure("Atime should be restored");
1554         assertFileAtime("nd/f2", 886611, 0);
1555
1556         /* Destroy the disk object. */
1557         assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1558         archive_entry_free(ae);
1559 }
1560
1561 DEFINE_TEST(test_read_disk_directory_traversals)
1562 {
1563         /* Basic test. */
1564         test_basic();
1565         /* Test hybird mode; follow symlink initially, then not. */
1566         test_symlink_hybrid();
1567         /* Test logcal mode; follow all symlinks. */
1568         test_symlink_logical();
1569         /* Test logcal mode; prevent loop in symlinks. */ 
1570         test_symlink_logical_loop();
1571         /* Test to restore atime. */
1572         test_restore_atime();
1573         /* Test callbacks. */
1574         test_callbacks();
1575         /* Test nodump. */
1576         test_nodump();
1577 }