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