test_read_disk_directory_traversals.c revision 313570
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 filesystem is mounted with noatime option.
37 */
38static int
39atimeIsUpdated(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
59static void
60test_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 perform 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
552static void
553test_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
709static void
710test_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
939static void
940test_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
1018static void
1019test_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
1278static int
1279metadata_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
1302static void
1303test_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	assert((a = archive_read_disk_new()) != NULL);
1324	if (a == NULL) {
1325		archive_entry_free(ae);
1326		return;
1327	}
1328	assert((m = archive_match_new()) != NULL);
1329	if (m == NULL) {
1330		archive_entry_free(ae);
1331		archive_read_free(a);
1332		archive_match_free(m);
1333		return;
1334	}
1335
1336	/*
1337	 * Test1: Traversals with a name filter.
1338	 */
1339	file_count = 3;
1340	assertEqualIntA(m, ARCHIVE_OK,
1341	    archive_match_exclude_pattern(m, "cb/f2"));
1342	assertEqualIntA(a, ARCHIVE_OK,
1343	    archive_read_disk_set_matching(a, m, NULL, NULL));
1344	failure("Directory traversals should work as well");
1345	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
1346	while (file_count--) {
1347		archive_entry_clear(ae);
1348		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1349		failure("File 'cb/f2' should be exclueded");
1350		assert(strcmp(archive_entry_pathname(ae), "cb/f2") != 0);
1351		if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
1352			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1353		} else if (strcmp(archive_entry_pathname(ae), "cb/f1") == 0) {
1354			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1355			assertEqualInt(archive_entry_size(ae), 10);
1356			assertEqualIntA(a, ARCHIVE_OK,
1357			    archive_read_data_block(a, &p, &size, &offset));
1358			assertEqualInt((int)size, 10);
1359			assertEqualInt((int)offset, 0);
1360			assertEqualMem(p, "0123456789", 10);
1361			assertEqualInt(ARCHIVE_EOF,
1362			    archive_read_data_block(a, &p, &size, &offset));
1363			assertEqualInt((int)size, 0);
1364			assertEqualInt((int)offset, 10);
1365		} else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
1366			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1367			assertEqualInt(archive_entry_size(ae), 0);
1368		}
1369		if (archive_read_disk_can_descend(a)) {
1370			/* Descend into the current object */
1371			assertEqualIntA(a, ARCHIVE_OK,
1372			    archive_read_disk_descend(a));
1373		}
1374	}
1375	/* There is no entry. */
1376	failure("There should be no entry");
1377	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1378
1379	/* Close the disk object. */
1380	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1381
1382	/* Reset name filter */
1383	assertEqualIntA(a, ARCHIVE_OK,
1384	    archive_read_disk_set_matching(a, NULL, NULL, NULL));
1385
1386	/*
1387	 * Test2: Traversals with a metadata filter.
1388	 */
1389	assertUtimes("cb/f1", 886600, 0, 886600, 0);
1390	assertUtimes("cb/f2", 886611, 0, 886611, 0);
1391	assertUtimes("cb/fe", 886611, 0, 886611, 0);
1392	assertUtimes("cb", 886622, 0, 886622, 0);
1393	file_count = 3;
1394	assertEqualIntA(a, ARCHIVE_OK,
1395	    archive_read_disk_set_metadata_filter_callback(a, metadata_filter,
1396		    NULL));
1397	failure("Directory traversals should work as well");
1398	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
1399
1400	while (file_count--) {
1401		archive_entry_clear(ae);
1402		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1403		failure("File 'cb/f1' should be excluded");
1404		assert(strcmp(archive_entry_pathname(ae), "cb/f1") != 0);
1405		if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
1406			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1407		} else if (strcmp(archive_entry_pathname(ae), "cb/f2") == 0) {
1408			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1409			assertEqualInt(archive_entry_size(ae), 11);
1410			assertEqualIntA(a, ARCHIVE_OK,
1411			    archive_read_data_block(a, &p, &size, &offset));
1412			assertEqualInt((int)size, 11);
1413			assertEqualInt((int)offset, 0);
1414			assertEqualMem(p, "hello world", 11);
1415			assertEqualInt(ARCHIVE_EOF,
1416			    archive_read_data_block(a, &p, &size, &offset));
1417			assertEqualInt((int)size, 0);
1418			assertEqualInt((int)offset, 11);
1419		} else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
1420			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1421			assertEqualInt(archive_entry_size(ae), 0);
1422		}
1423	}
1424	/* There is no entry. */
1425	failure("There should be no entry");
1426	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1427
1428	/* Destroy the disk object. */
1429	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1430	assertEqualInt(ARCHIVE_OK, archive_match_free(m));
1431	archive_entry_free(ae);
1432}
1433
1434static void
1435test_nodump(void)
1436{
1437	struct archive *a;
1438	struct archive_entry *ae;
1439	const void *p;
1440	size_t size;
1441	int64_t offset;
1442	int file_count;
1443
1444	if (!canNodump()) {
1445		skipping("Can't test nodump on this filesystem");
1446		return;
1447	}
1448
1449	assertMakeDir("nd", 0755);
1450	assertMakeFile("nd/f1", 0644, "0123456789");
1451	assertMakeFile("nd/f2", 0644, "hello world");
1452	assertMakeFile("nd/fe", 0644, NULL);
1453	assertNodump("nd/f2");
1454	assertUtimes("nd/f1", 886600, 0, 886600, 0);
1455	assertUtimes("nd/f2", 886611, 0, 886611, 0);
1456	assertUtimes("nd/fe", 886611, 0, 886611, 0);
1457	assertUtimes("nd", 886622, 0, 886622, 0);
1458
1459	assert((ae = archive_entry_new()) != NULL);
1460	assert((a = archive_read_disk_new()) != NULL);
1461
1462	/*
1463	 * Test1: Traversals without archive_read_disk_honor_nodump().
1464	 */
1465	failure("Directory traversals should work as well");
1466	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
1467
1468	file_count = 4;
1469	while (file_count--) {
1470		archive_entry_clear(ae);
1471		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1472		if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
1473			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1474		} else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) {
1475			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1476			assertEqualInt(archive_entry_size(ae), 10);
1477			assertEqualIntA(a, ARCHIVE_OK,
1478			    archive_read_data_block(a, &p, &size, &offset));
1479			assertEqualInt((int)size, 10);
1480			assertEqualInt((int)offset, 0);
1481			assertEqualMem(p, "0123456789", 10);
1482			assertEqualInt(ARCHIVE_EOF,
1483			    archive_read_data_block(a, &p, &size, &offset));
1484			assertEqualInt((int)size, 0);
1485			assertEqualInt((int)offset, 10);
1486		} else if (strcmp(archive_entry_pathname(ae), "nd/f2") == 0) {
1487			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1488			assertEqualInt(archive_entry_size(ae), 11);
1489			assertEqualIntA(a, ARCHIVE_OK,
1490			    archive_read_data_block(a, &p, &size, &offset));
1491			assertEqualInt((int)size, 11);
1492			assertEqualInt((int)offset, 0);
1493			assertEqualMem(p, "hello world", 11);
1494			assertEqualInt(ARCHIVE_EOF,
1495			    archive_read_data_block(a, &p, &size, &offset));
1496			assertEqualInt((int)size, 0);
1497			assertEqualInt((int)offset, 11);
1498		} else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
1499			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1500			assertEqualInt(archive_entry_size(ae), 0);
1501		}
1502		if (archive_read_disk_can_descend(a)) {
1503			/* Descend into the current object */
1504			assertEqualIntA(a, ARCHIVE_OK,
1505			    archive_read_disk_descend(a));
1506		}
1507	}
1508	/* There is no entry. */
1509	failure("There should be no entry");
1510	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1511
1512	/* Close the disk object. */
1513	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1514
1515	/*
1516	 * Test2: Traversals with archive_read_disk_honor_nodump().
1517	 */
1518	assertUtimes("nd/f1", 886600, 0, 886600, 0);
1519	assertUtimes("nd/f2", 886611, 0, 886611, 0);
1520	assertUtimes("nd/fe", 886611, 0, 886611, 0);
1521	assertUtimes("nd", 886622, 0, 886622, 0);
1522
1523	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a,
1524		ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP));
1525	failure("Directory traversals should work as well");
1526	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
1527
1528	file_count = 3;
1529	while (file_count--) {
1530		archive_entry_clear(ae);
1531		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1532		failure("File 'nd/f2' should be exclueded");
1533		assert(strcmp(archive_entry_pathname(ae), "nd/f2") != 0);
1534		if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
1535			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1536		} else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) {
1537			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1538			assertEqualInt(archive_entry_size(ae), 10);
1539			assertEqualIntA(a, ARCHIVE_OK,
1540			    archive_read_data_block(a, &p, &size, &offset));
1541			assertEqualInt((int)size, 10);
1542			assertEqualInt((int)offset, 0);
1543			assertEqualMem(p, "0123456789", 10);
1544			assertEqualInt(ARCHIVE_EOF,
1545			    archive_read_data_block(a, &p, &size, &offset));
1546			assertEqualInt((int)size, 0);
1547			assertEqualInt((int)offset, 10);
1548		} else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
1549			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1550			assertEqualInt(archive_entry_size(ae), 0);
1551		}
1552		if (archive_read_disk_can_descend(a)) {
1553			/* Descend into the current object */
1554			assertEqualIntA(a, ARCHIVE_OK,
1555			    archive_read_disk_descend(a));
1556		}
1557	}
1558	/* There is no entry. */
1559	failure("There should be no entry");
1560	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1561
1562	failure("Atime should be restored");
1563	assertFileAtime("nd/f2", 886611, 0);
1564
1565	/* Destroy the disk object. */
1566	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1567	archive_entry_free(ae);
1568}
1569
1570DEFINE_TEST(test_read_disk_directory_traversals)
1571{
1572	/* Basic test. */
1573	test_basic();
1574	/* Test hybrid mode; follow symlink initially, then not. */
1575	test_symlink_hybrid();
1576	/* Test logical mode; follow all symlinks. */
1577	test_symlink_logical();
1578	/* Test logical mode; prevent loop in symlinks. */
1579	test_symlink_logical_loop();
1580	/* Test to restore atime. */
1581	test_restore_atime();
1582	/* Test callbacks. */
1583	test_callbacks();
1584	/* Test nodump. */
1585	test_nodump();
1586}
1587