1231200Smm/*-
2238856Smm * Copyright (c) 2010-2012 Michihiro NAKAJIMA
3231200Smm * All rights reserved.
4231200Smm *
5231200Smm * Redistribution and use in source and binary forms, with or without
6231200Smm * modification, are permitted provided that the following conditions
7231200Smm * are met:
8231200Smm * 1. Redistributions of source code must retain the above copyright
9231200Smm *    notice, this list of conditions and the following disclaimer.
10231200Smm * 2. Redistributions in binary form must reproduce the above copyright
11231200Smm *    notice, this list of conditions and the following disclaimer in the
12231200Smm *    documentation and/or other materials provided with the distribution.
13231200Smm *
14231200Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15231200Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16231200Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17231200Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18231200Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19231200Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20231200Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21231200Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22231200Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23231200Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24231200Smm */
25231200Smm#include "test.h"
26231200Smm__FBSDID("$FreeBSD$");
27231200Smm
28231200Smm#include <limits.h>
29231200Smm#if defined(_WIN32) && !defined(__CYGWIN__)
30231200Smm# if !defined(__BORLANDC__)
31231200Smm#  define getcwd _getcwd
32231200Smm# endif
33231200Smm#endif
34231200Smm
35231200Smm/*
36231200Smm * Test if the current filesytem is mounted with noatime option.
37231200Smm */
38231200Smmstatic int
39231200SmmatimeIsUpdated(void)
40231200Smm{
41231200Smm	const char *fn = "fs_noatime";
42231200Smm	struct stat st;
43231200Smm
44231200Smm	if (!assertMakeFile(fn, 0666, "a"))
45231200Smm		return (0);
46231200Smm	if (!assertUtimes(fn, 1, 0, 1, 0))
47231200Smm		return (0);
48231200Smm	/* Test the file contents in order to update its atime. */
49231200Smm	if (!assertTextFileContents("a", fn))
50231200Smm		return (0);
51231200Smm	if (stat(fn, &st) != 0)
52231200Smm		return (0);
53231200Smm	/* Is atime updated? */
54231200Smm	if (st.st_atime > 1)
55231200Smm		return (1);
56231200Smm	return (0);
57231200Smm}
58231200Smm
59231200Smmstatic void
60231200Smmtest_basic(void)
61231200Smm{
62231200Smm	struct archive *a;
63231200Smm	struct archive_entry *ae;
64231200Smm	const void *p;
65231200Smm	char *initial_cwd, *cwd;
66231200Smm	size_t size;
67231200Smm	int64_t offset;
68231200Smm	int file_count;
69238856Smm#if defined(_WIN32) && !defined(__CYGWIN__)
70238856Smm	wchar_t *wcwd, *wp, *fullpath;
71238856Smm#endif
72231200Smm
73231200Smm	assertMakeDir("dir1", 0755);
74231200Smm	assertMakeFile("dir1/file1", 0644, "0123456789");
75231200Smm	assertMakeFile("dir1/file2", 0644, "hello world");
76231200Smm	assertMakeDir("dir1/sub1", 0755);
77231200Smm	assertMakeFile("dir1/sub1/file1", 0644, "0123456789");
78231200Smm	assertMakeDir("dir1/sub2", 0755);
79231200Smm	assertMakeFile("dir1/sub2/file1", 0644, "0123456789");
80231200Smm	assertMakeFile("dir1/sub2/file2", 0644, "0123456789");
81231200Smm	assertMakeDir("dir1/sub2/sub1", 0755);
82231200Smm	assertMakeDir("dir1/sub2/sub2", 0755);
83231200Smm	assertMakeDir("dir1/sub2/sub3", 0755);
84231200Smm	assertMakeFile("dir1/sub2/sub3/file", 0644, "xyz");
85231200Smm	file_count = 12;
86231200Smm
87231200Smm	assert((ae = archive_entry_new()) != NULL);
88231200Smm	assert((a = archive_read_disk_new()) != NULL);
89231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1"));
90231200Smm
91231200Smm	while (file_count--) {
92231200Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
93231200Smm		if (strcmp(archive_entry_pathname(ae), "dir1") == 0) {
94231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
95238856Smm			assertEqualInt(1, archive_read_disk_can_descend(a));
96231200Smm		} else if (strcmp(archive_entry_pathname(ae),
97231200Smm		    "dir1/file1") == 0) {
98231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
99231200Smm			assertEqualInt(archive_entry_size(ae), 10);
100231200Smm			assertEqualIntA(a, ARCHIVE_OK,
101231200Smm			    archive_read_data_block(a, &p, &size, &offset));
102231200Smm			assertEqualInt((int)size, 10);
103231200Smm			assertEqualInt((int)offset, 0);
104231200Smm			assertEqualMem(p, "0123456789", 10);
105231200Smm			assertEqualInt(ARCHIVE_EOF,
106231200Smm			    archive_read_data_block(a, &p, &size, &offset));
107231200Smm			assertEqualInt((int)size, 0);
108231200Smm			assertEqualInt((int)offset, 10);
109238856Smm			assertEqualInt(0, archive_read_disk_can_descend(a));
110231200Smm		} else if (strcmp(archive_entry_pathname(ae),
111231200Smm		    "dir1/file2") == 0) {
112231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
113231200Smm			assertEqualInt(archive_entry_size(ae), 11);
114231200Smm			assertEqualIntA(a, ARCHIVE_OK,
115231200Smm			    archive_read_data_block(a, &p, &size, &offset));
116231200Smm			assertEqualInt((int)size, 11);
117231200Smm			assertEqualInt((int)offset, 0);
118231200Smm			assertEqualMem(p, "hello world", 11);
119231200Smm			assertEqualInt(ARCHIVE_EOF,
120231200Smm			    archive_read_data_block(a, &p, &size, &offset));
121231200Smm			assertEqualInt((int)size, 0);
122231200Smm			assertEqualInt((int)offset, 11);
123238856Smm			assertEqualInt(0, archive_read_disk_can_descend(a));
124231200Smm		} else if (strcmp(archive_entry_pathname(ae),
125231200Smm		    "dir1/sub1") == 0) {
126231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
127238856Smm			assertEqualInt(1, archive_read_disk_can_descend(a));
128231200Smm		} else if (strcmp(archive_entry_pathname(ae),
129231200Smm		    "dir1/sub1/file1") == 0) {
130231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
131231200Smm			assertEqualInt(archive_entry_size(ae), 10);
132231200Smm			assertEqualIntA(a, ARCHIVE_OK,
133231200Smm			    archive_read_data_block(a, &p, &size, &offset));
134231200Smm			assertEqualInt((int)size, 10);
135231200Smm			assertEqualInt((int)offset, 0);
136231200Smm			assertEqualMem(p, "0123456789", 10);
137231200Smm			assertEqualInt(ARCHIVE_EOF,
138231200Smm			    archive_read_data_block(a, &p, &size, &offset));
139231200Smm			assertEqualInt((int)size, 0);
140231200Smm			assertEqualInt((int)offset, 10);
141238856Smm			assertEqualInt(0, archive_read_disk_can_descend(a));
142231200Smm		} else if (strcmp(archive_entry_pathname(ae),
143231200Smm		    "dir1/sub2") == 0) {
144231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
145238856Smm			assertEqualInt(1, archive_read_disk_can_descend(a));
146231200Smm		} else if (strcmp(archive_entry_pathname(ae),
147231200Smm		    "dir1/sub2/file1") == 0) {
148231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
149231200Smm			assertEqualInt(archive_entry_size(ae), 10);
150231200Smm			assertEqualIntA(a, ARCHIVE_OK,
151231200Smm			    archive_read_data_block(a, &p, &size, &offset));
152231200Smm			assertEqualInt((int)size, 10);
153231200Smm			assertEqualInt((int)offset, 0);
154231200Smm			assertEqualMem(p, "0123456789", 10);
155231200Smm			assertEqualInt(ARCHIVE_EOF,
156231200Smm			    archive_read_data_block(a, &p, &size, &offset));
157231200Smm			assertEqualInt((int)size, 0);
158231200Smm			assertEqualInt((int)offset, 10);
159238856Smm			assertEqualInt(0, archive_read_disk_can_descend(a));
160231200Smm		} else if (strcmp(archive_entry_pathname(ae),
161231200Smm		    "dir1/sub2/file2") == 0) {
162231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
163231200Smm			assertEqualInt(archive_entry_size(ae), 10);
164231200Smm			assertEqualIntA(a, ARCHIVE_OK,
165231200Smm			    archive_read_data_block(a, &p, &size, &offset));
166231200Smm			assertEqualInt((int)size, 10);
167231200Smm			assertEqualInt((int)offset, 0);
168231200Smm			assertEqualMem(p, "0123456789", 10);
169231200Smm			assertEqualInt(ARCHIVE_EOF,
170231200Smm			    archive_read_data_block(a, &p, &size, &offset));
171231200Smm			assertEqualInt((int)size, 0);
172231200Smm			assertEqualInt((int)offset, 10);
173238856Smm			assertEqualInt(0, archive_read_disk_can_descend(a));
174231200Smm		} else if (strcmp(archive_entry_pathname(ae),
175231200Smm		    "dir1/sub2/sub1") == 0) {
176231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
177238856Smm			assertEqualInt(1, archive_read_disk_can_descend(a));
178231200Smm		} else if (strcmp(archive_entry_pathname(ae),
179231200Smm		    "dir1/sub2/sub2") == 0) {
180231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
181238856Smm			assertEqualInt(1, archive_read_disk_can_descend(a));
182231200Smm		} else if (strcmp(archive_entry_pathname(ae),
183231200Smm		    "dir1/sub2/sub3") == 0) {
184231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
185238856Smm			assertEqualInt(1, archive_read_disk_can_descend(a));
186231200Smm		} else if (strcmp(archive_entry_pathname(ae),
187231200Smm		    "dir1/sub2/sub3/file") == 0) {
188231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
189231200Smm			assertEqualInt(archive_entry_size(ae), 3);
190231200Smm			assertEqualIntA(a, ARCHIVE_OK,
191231200Smm			    archive_read_data_block(a, &p, &size, &offset));
192231200Smm			assertEqualInt((int)size, 3);
193231200Smm			assertEqualInt((int)offset, 0);
194231200Smm			assertEqualMem(p, "xyz", 3);
195231200Smm			assertEqualInt(ARCHIVE_EOF,
196231200Smm			    archive_read_data_block(a, &p, &size, &offset));
197231200Smm			assertEqualInt((int)size, 0);
198231200Smm			assertEqualInt((int)offset, 3);
199238856Smm			assertEqualInt(0, archive_read_disk_can_descend(a));
200231200Smm		}
201231200Smm		if (archive_entry_filetype(ae) == AE_IFDIR) {
202231200Smm			/* Descend into the current object */
203231200Smm			assertEqualIntA(a, ARCHIVE_OK,
204231200Smm			    archive_read_disk_descend(a));
205231200Smm		}
206231200Smm	}
207231200Smm	/* There is no entry. */
208231200Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
209231200Smm
210231200Smm	/* Close the disk object. */
211231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
212231200Smm
213231200Smm	/*
214231200Smm	 * Test that call archive_read_disk_open_w, wchar_t version.
215231200Smm	 */
216231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, L"dir1"));
217231200Smm
218231200Smm	file_count = 12;
219231200Smm	while (file_count--) {
220231200Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
221231200Smm		if (wcscmp(archive_entry_pathname_w(ae), L"dir1") == 0) {
222231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
223238856Smm			assertEqualInt(1, archive_read_disk_can_descend(a));
224231200Smm		} else if (wcscmp(archive_entry_pathname_w(ae),
225231200Smm		    L"dir1/file1") == 0) {
226231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
227231200Smm			assertEqualInt(archive_entry_size(ae), 10);
228231200Smm			assertEqualIntA(a, ARCHIVE_OK,
229231200Smm			    archive_read_data_block(a, &p, &size, &offset));
230231200Smm			assertEqualInt((int)size, 10);
231231200Smm			assertEqualInt((int)offset, 0);
232231200Smm			assertEqualMem(p, "0123456789", 10);
233231200Smm			assertEqualInt(ARCHIVE_EOF,
234231200Smm			    archive_read_data_block(a, &p, &size, &offset));
235231200Smm			assertEqualInt((int)size, 0);
236231200Smm			assertEqualInt((int)offset, 10);
237238856Smm			assertEqualInt(0, archive_read_disk_can_descend(a));
238231200Smm		} else if (wcscmp(archive_entry_pathname_w(ae),
239231200Smm		    L"dir1/file2") == 0) {
240231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
241231200Smm			assertEqualInt(archive_entry_size(ae), 11);
242231200Smm			assertEqualIntA(a, ARCHIVE_OK,
243231200Smm			    archive_read_data_block(a, &p, &size, &offset));
244231200Smm			assertEqualInt((int)size, 11);
245231200Smm			assertEqualInt((int)offset, 0);
246231200Smm			assertEqualMem(p, "hello world", 11);
247231200Smm			assertEqualInt(ARCHIVE_EOF,
248231200Smm			    archive_read_data_block(a, &p, &size, &offset));
249231200Smm			assertEqualInt((int)size, 0);
250231200Smm			assertEqualInt((int)offset, 11);
251238856Smm			assertEqualInt(0, archive_read_disk_can_descend(a));
252231200Smm		} else if (wcscmp(archive_entry_pathname_w(ae),
253231200Smm		    L"dir1/sub1") == 0) {
254231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
255238856Smm			assertEqualInt(1, archive_read_disk_can_descend(a));
256231200Smm		} else if (wcscmp(archive_entry_pathname_w(ae),
257231200Smm		    L"dir1/sub1/file1") == 0) {
258231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
259231200Smm			assertEqualInt(archive_entry_size(ae), 10);
260231200Smm			assertEqualIntA(a, ARCHIVE_OK,
261231200Smm			    archive_read_data_block(a, &p, &size, &offset));
262231200Smm			assertEqualInt((int)size, 10);
263231200Smm			assertEqualInt((int)offset, 0);
264231200Smm			assertEqualMem(p, "0123456789", 10);
265231200Smm			assertEqualInt(ARCHIVE_EOF,
266231200Smm			    archive_read_data_block(a, &p, &size, &offset));
267231200Smm			assertEqualInt((int)size, 0);
268231200Smm			assertEqualInt((int)offset, 10);
269238856Smm			assertEqualInt(0, archive_read_disk_can_descend(a));
270231200Smm		} else if (wcscmp(archive_entry_pathname_w(ae),
271231200Smm		    L"dir1/sub2") == 0) {
272231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
273238856Smm			assertEqualInt(1, archive_read_disk_can_descend(a));
274231200Smm		} else if (wcscmp(archive_entry_pathname_w(ae),
275231200Smm		    L"dir1/sub2/file1") == 0) {
276231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
277231200Smm			assertEqualInt(archive_entry_size(ae), 10);
278231200Smm			assertEqualIntA(a, ARCHIVE_OK,
279231200Smm			    archive_read_data_block(a, &p, &size, &offset));
280231200Smm			assertEqualInt((int)size, 10);
281231200Smm			assertEqualInt((int)offset, 0);
282231200Smm			assertEqualMem(p, "0123456789", 10);
283231200Smm			assertEqualInt(ARCHIVE_EOF,
284231200Smm			    archive_read_data_block(a, &p, &size, &offset));
285231200Smm			assertEqualInt((int)size, 0);
286231200Smm			assertEqualInt((int)offset, 10);
287238856Smm			assertEqualInt(0, archive_read_disk_can_descend(a));
288231200Smm		} else if (wcscmp(archive_entry_pathname_w(ae),
289231200Smm		    L"dir1/sub2/file2") == 0) {
290231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
291231200Smm			assertEqualInt(archive_entry_size(ae), 10);
292231200Smm			assertEqualIntA(a, ARCHIVE_OK,
293231200Smm			    archive_read_data_block(a, &p, &size, &offset));
294231200Smm			assertEqualInt((int)size, 10);
295231200Smm			assertEqualInt((int)offset, 0);
296231200Smm			assertEqualMem(p, "0123456789", 10);
297231200Smm			assertEqualInt(ARCHIVE_EOF,
298231200Smm			    archive_read_data_block(a, &p, &size, &offset));
299231200Smm			assertEqualInt((int)size, 0);
300231200Smm			assertEqualInt((int)offset, 10);
301238856Smm			assertEqualInt(0, archive_read_disk_can_descend(a));
302231200Smm		} else if (wcscmp(archive_entry_pathname_w(ae),
303231200Smm		    L"dir1/sub2/sub1") == 0) {
304231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
305238856Smm			assertEqualInt(1, archive_read_disk_can_descend(a));
306231200Smm		} else if (wcscmp(archive_entry_pathname_w(ae),
307231200Smm		    L"dir1/sub2/sub2") == 0) {
308231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
309238856Smm			assertEqualInt(1, archive_read_disk_can_descend(a));
310231200Smm		} else if (wcscmp(archive_entry_pathname_w(ae),
311231200Smm		    L"dir1/sub2/sub3") == 0) {
312231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
313238856Smm			assertEqualInt(1, archive_read_disk_can_descend(a));
314231200Smm		} else if (wcscmp(archive_entry_pathname_w(ae),
315231200Smm		    L"dir1/sub2/sub3/file") == 0) {
316231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
317231200Smm			assertEqualInt(archive_entry_size(ae), 3);
318231200Smm			assertEqualIntA(a, ARCHIVE_OK,
319231200Smm			    archive_read_data_block(a, &p, &size, &offset));
320231200Smm			assertEqualInt((int)size, 3);
321231200Smm			assertEqualInt((int)offset, 0);
322231200Smm			assertEqualMem(p, "xyz", 3);
323231200Smm			assertEqualInt(ARCHIVE_EOF,
324231200Smm			    archive_read_data_block(a, &p, &size, &offset));
325231200Smm			assertEqualInt((int)size, 0);
326231200Smm			assertEqualInt((int)offset, 3);
327238856Smm			assertEqualInt(0, archive_read_disk_can_descend(a));
328231200Smm		}
329231200Smm		if (archive_entry_filetype(ae) == AE_IFDIR) {
330231200Smm			/* Descend into the current object */
331231200Smm			assertEqualIntA(a, ARCHIVE_OK,
332231200Smm			    archive_read_disk_descend(a));
333231200Smm		}
334231200Smm	}
335231200Smm	/* There is no entry. */
336231200Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
337231200Smm
338231200Smm	/* Close the disk object. */
339231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
340231200Smm
341231200Smm	/*
342231200Smm	 * Test that call archive_read_disk_open with a regular file.
343231200Smm	 */
344231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1/file1"));
345231200Smm
346231200Smm	/* dir1/file1 */
347231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
348238856Smm	assertEqualInt(0, archive_read_disk_can_descend(a));
349231200Smm	assertEqualString(archive_entry_pathname(ae), "dir1/file1");
350231200Smm	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
351231200Smm	assertEqualInt(archive_entry_size(ae), 10);
352231200Smm	assertEqualIntA(a, ARCHIVE_OK,
353231200Smm	    archive_read_data_block(a, &p, &size, &offset));
354231200Smm	assertEqualInt((int)size, 10);
355231200Smm	assertEqualInt((int)offset, 0);
356231200Smm	assertEqualMem(p, "0123456789", 10);
357231200Smm
358231200Smm	/* There is no entry. */
359231200Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
360231200Smm
361231200Smm	/* Close the disk object. */
362231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
363231200Smm
364231200Smm
365231200Smm#if defined(_WIN32) && !defined(__CYGWIN__)
366231200Smm	/*
367231200Smm	 * Test for wildcard '*' or '?'
368231200Smm	 */
369231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1/*1"));
370231200Smm
371231200Smm	/* dir1/file1 */
372231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
373238856Smm	assertEqualInt(0, archive_read_disk_can_descend(a));
374231200Smm	assertEqualString(archive_entry_pathname(ae), "dir1/file1");
375231200Smm	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
376231200Smm	assertEqualInt(archive_entry_size(ae), 10);
377231200Smm	assertEqualIntA(a, ARCHIVE_OK,
378231200Smm	    archive_read_data_block(a, &p, &size, &offset));
379231200Smm	assertEqualInt((int)size, 10);
380231200Smm	assertEqualInt((int)offset, 0);
381231200Smm	assertEqualMem(p, "0123456789", 10);
382231200Smm
383231200Smm	/* dir1/sub1 */
384231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
385238856Smm	assertEqualInt(1, archive_read_disk_can_descend(a));
386231200Smm	assertEqualString(archive_entry_pathname(ae), "dir1/sub1");
387231200Smm	assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
388231200Smm
389231200Smm	/* Descend into the current object */
390231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a));
391231200Smm
392231200Smm	/* dir1/sub1/file1 */
393231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
394238856Smm	assertEqualInt(0, archive_read_disk_can_descend(a));
395231200Smm	assertEqualString(archive_entry_pathname(ae), "dir1/sub1/file1");
396231200Smm	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
397231200Smm	assertEqualInt(archive_entry_size(ae), 10);
398231200Smm	assertEqualIntA(a, ARCHIVE_OK,
399231200Smm	    archive_read_data_block(a, &p, &size, &offset));
400231200Smm	assertEqualInt((int)size, 10);
401231200Smm	assertEqualInt((int)offset, 0);
402231200Smm	assertEqualMem(p, "0123456789", 10);
403231200Smm
404231200Smm	/* There is no entry. */
405231200Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
406231200Smm
407231200Smm	/* Close the disk object. */
408231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
409238856Smm
410238856Smm	/*
411238856Smm	 * Test for a full-path beginning with "//?/"
412238856Smm	 */
413238856Smm	wcwd = _wgetcwd(NULL, 0);
414238856Smm	fullpath = malloc(sizeof(wchar_t) * (wcslen(wcwd) + 32));
415238856Smm	wcscpy(fullpath, L"//?/");
416238856Smm	wcscat(fullpath, wcwd);
417238856Smm	wcscat(fullpath, L"/dir1/file1");
418238856Smm	free(wcwd);
419238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, fullpath));
420238856Smm	while ((wcwd = wcschr(fullpath, L'\\')) != NULL)
421238856Smm		*wcwd = L'/';
422238856Smm
423238856Smm	/* dir1/file1 */
424238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
425238856Smm	assertEqualInt(0, archive_read_disk_can_descend(a));
426238856Smm	assertEqualWString(archive_entry_pathname_w(ae), fullpath);
427238856Smm	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
428238856Smm	assertEqualInt(archive_entry_size(ae), 10);
429238856Smm	assertEqualIntA(a, ARCHIVE_OK,
430238856Smm	    archive_read_data_block(a, &p, &size, &offset));
431238856Smm	assertEqualInt((int)size, 10);
432238856Smm	assertEqualInt((int)offset, 0);
433238856Smm	assertEqualMem(p, "0123456789", 10);
434238856Smm
435238856Smm	/* There is no entry. */
436238856Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
437238856Smm
438238856Smm	/* Close the disk object. */
439238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
440238856Smm	free(fullpath);
441238856Smm
442238856Smm	/*
443238856Smm	 * Test for wild card '*' or '?' with "//?/" prefix.
444238856Smm	 */
445238856Smm	wcwd = _wgetcwd(NULL, 0);
446238856Smm	fullpath = malloc(sizeof(wchar_t) * (wcslen(wcwd) + 32));
447238856Smm	wcscpy(fullpath, L"//?/");
448238856Smm	wcscat(fullpath, wcwd);
449238856Smm	wcscat(fullpath, L"/dir1/*1");
450238856Smm	free(wcwd);
451238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, fullpath));
452238856Smm	while ((wcwd = wcschr(fullpath, L'\\')) != NULL)
453238856Smm		*wcwd = L'/';
454238856Smm
455238856Smm	/* dir1/file1 */
456238856Smm	wp = wcsrchr(fullpath, L'/');
457238856Smm	wcscpy(wp+1, L"file1");
458238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
459238856Smm	assertEqualInt(0, archive_read_disk_can_descend(a));
460238856Smm	assertEqualWString(archive_entry_pathname_w(ae), fullpath);
461238856Smm	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
462238856Smm	assertEqualInt(archive_entry_size(ae), 10);
463238856Smm	assertEqualIntA(a, ARCHIVE_OK,
464238856Smm	    archive_read_data_block(a, &p, &size, &offset));
465238856Smm	assertEqualInt((int)size, 10);
466238856Smm	assertEqualInt((int)offset, 0);
467238856Smm	assertEqualMem(p, "0123456789", 10);
468238856Smm
469238856Smm	/* dir1/sub1 */
470238856Smm	wcscpy(wp+1, L"sub1");
471238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
472238856Smm	assertEqualInt(1, archive_read_disk_can_descend(a));
473238856Smm	assertEqualWString(archive_entry_pathname_w(ae), fullpath);
474238856Smm	assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
475238856Smm
476238856Smm	/* Descend into the current object */
477238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a));
478238856Smm
479238856Smm	/* dir1/sub1/file1 */
480238856Smm	wcscpy(wp+1, L"sub1/file1");
481238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
482238856Smm	assertEqualInt(0, archive_read_disk_can_descend(a));
483238856Smm	assertEqualWString(archive_entry_pathname_w(ae), fullpath);
484238856Smm	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
485238856Smm	assertEqualInt(archive_entry_size(ae), 10);
486238856Smm	assertEqualIntA(a, ARCHIVE_OK,
487238856Smm	    archive_read_data_block(a, &p, &size, &offset));
488238856Smm	assertEqualInt((int)size, 10);
489238856Smm	assertEqualInt((int)offset, 0);
490238856Smm	assertEqualMem(p, "0123456789", 10);
491238856Smm
492238856Smm	/* There is no entry. */
493238856Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
494238856Smm
495238856Smm	/* Close the disk object. */
496238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
497238856Smm	free(fullpath);
498238856Smm
499231200Smm#endif
500231200Smm
501231200Smm	/*
502231200Smm	 * We should be on the initial directory where we performed
503231200Smm	 * archive_read_disk_new() after we perfome archive_read_free()
504231200Smm	 *  even if we broke off the directory traversals.
505231200Smm	 */
506231200Smm
507231200Smm	/* Save current working directory. */
508231200Smm#ifdef PATH_MAX
509231200Smm	initial_cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
510231200Smm#else
511231200Smm	initial_cwd = getcwd(NULL, 0);
512231200Smm#endif
513231200Smm
514231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1"));
515231200Smm
516231200Smm	/* Step in a deep directory. */
517231200Smm	file_count = 12;
518231200Smm	while (file_count--) {
519231200Smm		assertEqualIntA(a, ARCHIVE_OK,
520231200Smm		    archive_read_next_header2(a, ae));
521231200Smm		if (strcmp(archive_entry_pathname(ae),
522231200Smm		    "dir1/sub1/file1") == 0)
523231200Smm			/*
524231200Smm			 * We are on an another directory at this time.
525231200Smm			 */
526231200Smm			break;
527231200Smm		if (archive_entry_filetype(ae) == AE_IFDIR) {
528231200Smm			/* Descend into the current object */
529231200Smm			assertEqualIntA(a, ARCHIVE_OK,
530231200Smm			    archive_read_disk_descend(a));
531231200Smm		}
532231200Smm	}
533231200Smm	/* Destroy the disk object. */
534231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
535231200Smm
536231200Smm	/* We should be on the initial working directory. */
537231200Smm	failure(
538231200Smm	    "Current working directory does not return to the initial"
539231200Smm	    "directory");
540231200Smm#ifdef PATH_MAX
541231200Smm	cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
542231200Smm#else
543231200Smm	cwd = getcwd(NULL, 0);
544231200Smm#endif
545231200Smm	assertEqualString(initial_cwd, cwd);
546231200Smm	free(initial_cwd);
547231200Smm	free(cwd);
548231200Smm
549231200Smm	archive_entry_free(ae);
550231200Smm}
551231200Smm
552231200Smmstatic void
553231200Smmtest_symlink_hybrid(void)
554231200Smm{
555231200Smm	struct archive *a;
556231200Smm	struct archive_entry *ae;
557231200Smm	const void *p;
558231200Smm	size_t size;
559231200Smm	int64_t offset;
560231200Smm	int file_count;
561231200Smm
562231200Smm	if (!canSymlink()) {
563231200Smm		skipping("Can't test symlinks on this filesystem");
564231200Smm		return;
565231200Smm	}
566231200Smm
567231200Smm	/*
568231200Smm	 * Create a sample archive.
569231200Smm	 */
570231200Smm	assertMakeDir("h", 0755);
571231200Smm	assertChdir("h");
572231200Smm	assertMakeDir("d1", 0755);
573231200Smm	assertMakeSymlink("ld1", "d1");
574231200Smm	assertMakeFile("d1/file1", 0644, "d1/file1");
575231200Smm	assertMakeFile("d1/file2", 0644, "d1/file2");
576231200Smm	assertMakeSymlink("d1/link1", "file1");
577231200Smm	assertMakeSymlink("d1/linkX", "fileX");
578231200Smm	assertMakeSymlink("link2", "d1/file2");
579231200Smm	assertMakeSymlink("linkY", "d1/fileY");
580231200Smm	assertChdir("..");
581231200Smm
582231200Smm	assert((ae = archive_entry_new()) != NULL);
583231200Smm	assert((a = archive_read_disk_new()) != NULL);
584231200Smm	assertEqualIntA(a, ARCHIVE_OK,
585231200Smm	    archive_read_disk_set_symlink_hybrid(a));
586231200Smm
587231200Smm	/*
588231200Smm	 * Specified file is a symbolic link file.
589231200Smm	 */
590231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "h/ld1"));
591231200Smm	file_count = 5;
592231200Smm
593231200Smm	while (file_count--) {
594231200Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
595231200Smm		if (strcmp(archive_entry_pathname(ae), "h/ld1") == 0) {
596231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
597231200Smm		} else if (strcmp(archive_entry_pathname(ae),
598231200Smm		    "h/ld1/file1") == 0) {
599231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
600231200Smm			assertEqualInt(archive_entry_size(ae), 8);
601231200Smm			assertEqualIntA(a, ARCHIVE_OK,
602231200Smm			    archive_read_data_block(a, &p, &size, &offset));
603231200Smm			assertEqualInt((int)size, 8);
604231200Smm			assertEqualInt((int)offset, 0);
605231200Smm			assertEqualMem(p, "d1/file1", 8);
606231200Smm			assertEqualInt(ARCHIVE_EOF,
607231200Smm			    archive_read_data_block(a, &p, &size, &offset));
608231200Smm			assertEqualInt((int)size, 0);
609231200Smm			assertEqualInt((int)offset, 8);
610231200Smm		} else if (strcmp(archive_entry_pathname(ae),
611231200Smm		    "h/ld1/file2") == 0) {
612231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
613231200Smm			assertEqualInt(archive_entry_size(ae), 8);
614231200Smm			assertEqualIntA(a, ARCHIVE_OK,
615231200Smm			    archive_read_data_block(a, &p, &size, &offset));
616231200Smm			assertEqualInt((int)size, 8);
617231200Smm			assertEqualInt((int)offset, 0);
618231200Smm			assertEqualMem(p, "d1/file2", 8);
619231200Smm			assertEqualInt(ARCHIVE_EOF,
620231200Smm			    archive_read_data_block(a, &p, &size, &offset));
621231200Smm			assertEqualInt((int)size, 0);
622231200Smm			assertEqualInt((int)offset, 8);
623231200Smm		} else if (strcmp(archive_entry_pathname(ae),
624231200Smm		    "h/ld1/link1") == 0) {
625231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
626231200Smm		} else if (strcmp(archive_entry_pathname(ae),
627231200Smm		    "h/ld1/linkX") == 0) {
628231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
629231200Smm		}
630231200Smm		if (archive_entry_filetype(ae) == AE_IFDIR) {
631231200Smm			/* Descend into the current object */
632231200Smm			assertEqualIntA(a, ARCHIVE_OK,
633231200Smm			    archive_read_disk_descend(a));
634231200Smm		}
635231200Smm	}
636231200Smm	/* There is no entry. */
637231200Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
638231200Smm	/* Close the disk object. */
639231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
640231200Smm
641231200Smm	/*
642231200Smm	 * Specified file is a directory and it has symbolic files.
643231200Smm	 */
644231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "h"));
645231200Smm	file_count = 9;
646231200Smm
647231200Smm	while (file_count--) {
648231200Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
649231200Smm		if (strcmp(archive_entry_pathname(ae), "h") == 0) {
650231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
651231200Smm		} else if (strcmp(archive_entry_pathname(ae), "h/d1") == 0) {
652231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
653231200Smm		} else if (strcmp(archive_entry_pathname(ae),
654231200Smm		    "h/d1/file1") == 0) {
655231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
656231200Smm			assertEqualInt(archive_entry_size(ae), 8);
657231200Smm			assertEqualIntA(a, ARCHIVE_OK,
658231200Smm			    archive_read_data_block(a, &p, &size, &offset));
659231200Smm			assertEqualInt((int)size, 8);
660231200Smm			assertEqualInt((int)offset, 0);
661231200Smm			assertEqualMem(p, "d1/file1", 8);
662231200Smm			assertEqualInt(ARCHIVE_EOF,
663231200Smm			    archive_read_data_block(a, &p, &size, &offset));
664231200Smm			assertEqualInt((int)size, 0);
665231200Smm			assertEqualInt((int)offset, 8);
666231200Smm		} else if (strcmp(archive_entry_pathname(ae),
667231200Smm		    "h/d1/file2") == 0) {
668231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
669231200Smm			assertEqualInt(archive_entry_size(ae), 8);
670231200Smm			assertEqualIntA(a, ARCHIVE_OK,
671231200Smm			    archive_read_data_block(a, &p, &size, &offset));
672231200Smm			assertEqualInt((int)size, 8);
673231200Smm			assertEqualInt((int)offset, 0);
674231200Smm			assertEqualMem(p, "d1/file2", 8);
675231200Smm			assertEqualInt(ARCHIVE_EOF,
676231200Smm			    archive_read_data_block(a, &p, &size, &offset));
677231200Smm			assertEqualInt((int)size, 0);
678231200Smm			assertEqualInt((int)offset, 8);
679231200Smm		} else if (strcmp(archive_entry_pathname(ae), "h/ld1") == 0) {
680231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
681231200Smm		} else if (strcmp(archive_entry_pathname(ae),
682231200Smm		    "h/d1/link1") == 0) {
683231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
684231200Smm		} else if (strcmp(archive_entry_pathname(ae),
685231200Smm		    "h/d1/linkX") == 0) {
686231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
687231200Smm		} else if (strcmp(archive_entry_pathname(ae),
688231200Smm		    "h/link2") == 0) {
689231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
690231200Smm		} else if (strcmp(archive_entry_pathname(ae),
691231200Smm		    "h/linkY") == 0) {
692231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
693231200Smm		}
694231200Smm		if (archive_entry_filetype(ae) == AE_IFDIR) {
695231200Smm			/* Descend into the current object */
696231200Smm			assertEqualIntA(a, ARCHIVE_OK,
697231200Smm			    archive_read_disk_descend(a));
698231200Smm		}
699231200Smm	}
700231200Smm	/* There is no entry. */
701231200Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
702231200Smm	/* Close the disk object. */
703231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
704231200Smm	/* Destroy the disk object. */
705231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
706231200Smm	archive_entry_free(ae);
707231200Smm}
708231200Smm
709231200Smmstatic void
710231200Smmtest_symlink_logical(void)
711231200Smm{
712231200Smm	struct archive *a;
713231200Smm	struct archive_entry *ae;
714231200Smm	const void *p;
715231200Smm	size_t size;
716231200Smm	int64_t offset;
717231200Smm	int file_count;
718231200Smm
719231200Smm	if (!canSymlink()) {
720231200Smm		skipping("Can't test symlinks on this filesystem");
721231200Smm		return;
722231200Smm	}
723231200Smm
724231200Smm	/*
725231200Smm	 * Create a sample archive.
726231200Smm	 */
727231200Smm	assertMakeDir("l", 0755);
728231200Smm	assertChdir("l");
729231200Smm	assertMakeDir("d1", 0755);
730231200Smm	assertMakeSymlink("ld1", "d1");
731231200Smm	assertMakeFile("d1/file1", 0644, "d1/file1");
732231200Smm	assertMakeFile("d1/file2", 0644, "d1/file2");
733231200Smm	assertMakeSymlink("d1/link1", "file1");
734231200Smm	assertMakeSymlink("d1/linkX", "fileX");
735231200Smm	assertMakeSymlink("link2", "d1/file2");
736231200Smm	assertMakeSymlink("linkY", "d1/fileY");
737231200Smm	assertChdir("..");
738231200Smm
739299529Smm	/* Note: this test uses archive_read_next_header()
740299529Smm	   instead of archive_read_next_header2() */
741231200Smm	assert((a = archive_read_disk_new()) != NULL);
742231200Smm	assertEqualIntA(a, ARCHIVE_OK,
743231200Smm	    archive_read_disk_set_symlink_logical(a));
744231200Smm
745231200Smm	/*
746231200Smm	 * Specified file is a symbolic link file.
747231200Smm	 */
748231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l/ld1"));
749231200Smm	file_count = 5;
750231200Smm
751231200Smm	while (file_count--) {
752299529Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
753231200Smm		if (strcmp(archive_entry_pathname(ae), "l/ld1") == 0) {
754231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
755231200Smm		} else if (strcmp(archive_entry_pathname(ae),
756231200Smm		    "l/ld1/file1") == 0) {
757231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
758231200Smm			assertEqualInt(archive_entry_size(ae), 8);
759231200Smm			assertEqualIntA(a, ARCHIVE_OK,
760231200Smm			    archive_read_data_block(a, &p, &size, &offset));
761231200Smm			assertEqualInt((int)size, 8);
762231200Smm			assertEqualInt((int)offset, 0);
763231200Smm			assertEqualMem(p, "d1/file1", 8);
764231200Smm			assertEqualInt(ARCHIVE_EOF,
765231200Smm			    archive_read_data_block(a, &p, &size, &offset));
766231200Smm			assertEqualInt((int)size, 0);
767231200Smm			assertEqualInt((int)offset, 8);
768231200Smm		} else if (strcmp(archive_entry_pathname(ae),
769231200Smm		    "l/ld1/file2") == 0) {
770231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
771231200Smm			assertEqualInt(archive_entry_size(ae), 8);
772231200Smm			assertEqualIntA(a, ARCHIVE_OK,
773231200Smm			    archive_read_data_block(a, &p, &size, &offset));
774231200Smm			assertEqualInt((int)size, 8);
775231200Smm			assertEqualInt((int)offset, 0);
776231200Smm			assertEqualMem(p, "d1/file2", 8);
777231200Smm			assertEqualInt(ARCHIVE_EOF,
778231200Smm			    archive_read_data_block(a, &p, &size, &offset));
779231200Smm			assertEqualInt((int)size, 0);
780231200Smm			assertEqualInt((int)offset, 8);
781231200Smm		} else if (strcmp(archive_entry_pathname(ae),
782231200Smm		    "l/ld1/link1") == 0) {
783231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
784231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
785231200Smm			assertEqualInt(archive_entry_size(ae), 8);
786231200Smm			assertEqualIntA(a, ARCHIVE_OK,
787231200Smm			    archive_read_data_block(a, &p, &size, &offset));
788231200Smm			assertEqualInt((int)size, 8);
789231200Smm			assertEqualInt((int)offset, 0);
790231200Smm			assertEqualMem(p, "d1/file1", 8);
791231200Smm			assertEqualInt(ARCHIVE_EOF,
792231200Smm			    archive_read_data_block(a, &p, &size, &offset));
793231200Smm			assertEqualInt((int)size, 0);
794231200Smm			assertEqualInt((int)offset, 8);
795231200Smm		} else if (strcmp(archive_entry_pathname(ae),
796231200Smm		    "l/ld1/linkX") == 0) {
797231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
798231200Smm		}
799231200Smm		if (archive_entry_filetype(ae) == AE_IFDIR) {
800231200Smm			/* Descend into the current object */
801231200Smm			assertEqualIntA(a, ARCHIVE_OK,
802231200Smm			    archive_read_disk_descend(a));
803231200Smm		}
804231200Smm	}
805231200Smm	/* There is no entry. */
806299529Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
807231200Smm	/* Close the disk object. */
808231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
809231200Smm
810231200Smm	/*
811231200Smm	 * Specified file is a directory and it has symbolic files.
812231200Smm	 */
813231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l"));
814231200Smm	file_count = 13;
815231200Smm
816231200Smm	while (file_count--) {
817299529Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
818231200Smm		if (strcmp(archive_entry_pathname(ae), "l") == 0) {
819231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
820231200Smm		} else if (strcmp(archive_entry_pathname(ae), "l/d1") == 0) {
821231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
822231200Smm		} else if (strcmp(archive_entry_pathname(ae),
823231200Smm		    "l/d1/file1") == 0) {
824231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
825231200Smm			assertEqualInt(archive_entry_size(ae), 8);
826231200Smm			assertEqualIntA(a, ARCHIVE_OK,
827231200Smm			    archive_read_data_block(a, &p, &size, &offset));
828231200Smm			assertEqualInt((int)size, 8);
829231200Smm			assertEqualInt((int)offset, 0);
830231200Smm			assertEqualMem(p, "d1/file1", 8);
831231200Smm			assertEqualInt(ARCHIVE_EOF,
832231200Smm			    archive_read_data_block(a, &p, &size, &offset));
833231200Smm			assertEqualInt((int)size, 0);
834231200Smm			assertEqualInt((int)offset, 8);
835231200Smm		} else if (strcmp(archive_entry_pathname(ae),
836231200Smm		    "l/d1/file2") == 0) {
837231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
838231200Smm			assertEqualInt(archive_entry_size(ae), 8);
839231200Smm			assertEqualIntA(a, ARCHIVE_OK,
840231200Smm			    archive_read_data_block(a, &p, &size, &offset));
841231200Smm			assertEqualInt((int)size, 8);
842231200Smm			assertEqualInt((int)offset, 0);
843231200Smm			assertEqualMem(p, "d1/file2", 8);
844231200Smm			assertEqualInt(ARCHIVE_EOF,
845231200Smm			    archive_read_data_block(a, &p, &size, &offset));
846231200Smm			assertEqualInt((int)size, 0);
847231200Smm			assertEqualInt((int)offset, 8);
848231200Smm		} else if (strcmp(archive_entry_pathname(ae),
849231200Smm		    "l/d1/link1") == 0) {
850231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
851231200Smm			assertEqualInt(archive_entry_size(ae), 8);
852231200Smm			assertEqualIntA(a, ARCHIVE_OK,
853231200Smm			    archive_read_data_block(a, &p, &size, &offset));
854231200Smm			assertEqualInt((int)size, 8);
855231200Smm			assertEqualInt((int)offset, 0);
856231200Smm			assertEqualMem(p, "d1/file1", 8);
857231200Smm			assertEqualInt(ARCHIVE_EOF,
858231200Smm			    archive_read_data_block(a, &p, &size, &offset));
859231200Smm			assertEqualInt((int)size, 0);
860231200Smm			assertEqualInt((int)offset, 8);
861231200Smm		} else if (strcmp(archive_entry_pathname(ae),
862231200Smm		    "l/d1/linkX") == 0) {
863231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
864231200Smm		} else if (strcmp(archive_entry_pathname(ae), "l/ld1") == 0) {
865231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
866231200Smm		} else if (strcmp(archive_entry_pathname(ae),
867231200Smm		    "l/ld1/file1") == 0) {
868231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
869231200Smm			assertEqualInt(archive_entry_size(ae), 8);
870231200Smm			assertEqualIntA(a, ARCHIVE_OK,
871231200Smm			    archive_read_data_block(a, &p, &size, &offset));
872231200Smm			assertEqualInt((int)size, 8);
873231200Smm			assertEqualInt((int)offset, 0);
874231200Smm			assertEqualMem(p, "d1/file1", 8);
875231200Smm			assertEqualInt(ARCHIVE_EOF,
876231200Smm			    archive_read_data_block(a, &p, &size, &offset));
877231200Smm			assertEqualInt((int)size, 0);
878231200Smm			assertEqualInt((int)offset, 8);
879231200Smm		} else if (strcmp(archive_entry_pathname(ae),
880231200Smm		    "l/ld1/file2") == 0) {
881231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
882231200Smm			assertEqualInt(archive_entry_size(ae), 8);
883231200Smm			assertEqualIntA(a, ARCHIVE_OK,
884231200Smm			    archive_read_data_block(a, &p, &size, &offset));
885231200Smm			assertEqualInt((int)size, 8);
886231200Smm			assertEqualInt((int)offset, 0);
887231200Smm			assertEqualMem(p, "d1/file2", 8);
888231200Smm			assertEqualInt(ARCHIVE_EOF,
889231200Smm			    archive_read_data_block(a, &p, &size, &offset));
890231200Smm			assertEqualInt((int)size, 0);
891231200Smm			assertEqualInt((int)offset, 8);
892231200Smm		} else if (strcmp(archive_entry_pathname(ae),
893231200Smm		    "l/ld1/link1") == 0) {
894231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
895231200Smm			assertEqualInt(archive_entry_size(ae), 8);
896231200Smm			assertEqualIntA(a, ARCHIVE_OK,
897231200Smm			    archive_read_data_block(a, &p, &size, &offset));
898231200Smm			assertEqualInt((int)size, 8);
899231200Smm			assertEqualInt((int)offset, 0);
900231200Smm			assertEqualMem(p, "d1/file1", 8);
901231200Smm			assertEqualInt(ARCHIVE_EOF,
902231200Smm			    archive_read_data_block(a, &p, &size, &offset));
903231200Smm			assertEqualInt((int)size, 0);
904231200Smm			assertEqualInt((int)offset, 8);
905231200Smm		} else if (strcmp(archive_entry_pathname(ae),
906231200Smm		    "l/ld1/linkX") == 0) {
907231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
908231200Smm		} else if (strcmp(archive_entry_pathname(ae),
909231200Smm		    "l/link2") == 0) {
910231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
911231200Smm			assertEqualInt(archive_entry_size(ae), 8);
912231200Smm			assertEqualIntA(a, ARCHIVE_OK,
913231200Smm			    archive_read_data_block(a, &p, &size, &offset));
914231200Smm			assertEqualInt((int)size, 8);
915231200Smm			assertEqualInt((int)offset, 0);
916231200Smm			assertEqualMem(p, "d1/file2", 8);
917231200Smm			assertEqualInt(ARCHIVE_EOF,
918231200Smm			    archive_read_data_block(a, &p, &size, &offset));
919231200Smm			assertEqualInt((int)size, 0);
920231200Smm			assertEqualInt((int)offset, 8);
921231200Smm		} else if (strcmp(archive_entry_pathname(ae),
922231200Smm		    "l/linkY") == 0) {
923231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
924231200Smm		}
925231200Smm		if (archive_entry_filetype(ae) == AE_IFDIR) {
926231200Smm			/* Descend into the current object */
927231200Smm			assertEqualIntA(a, ARCHIVE_OK,
928231200Smm			    archive_read_disk_descend(a));
929231200Smm		}
930231200Smm	}
931231200Smm	/* There is no entry. */
932299529Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
933231200Smm	/* Close the disk object. */
934231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
935231200Smm	/* Destroy the disk object. */
936231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
937231200Smm}
938231200Smm
939231200Smmstatic void
940231200Smmtest_symlink_logical_loop(void)
941231200Smm{
942231200Smm	struct archive *a;
943231200Smm	struct archive_entry *ae;
944231200Smm	const void *p;
945231200Smm	size_t size;
946231200Smm	int64_t offset;
947231200Smm	int file_count;
948231200Smm
949231200Smm	if (!canSymlink()) {
950231200Smm		skipping("Can't test symlinks on this filesystem");
951231200Smm		return;
952231200Smm	}
953231200Smm
954231200Smm	/*
955231200Smm	 * Create a sample archive.
956231200Smm	 */
957231200Smm	assertMakeDir("l2", 0755);
958231200Smm	assertChdir("l2");
959231200Smm	assertMakeDir("d1", 0755);
960231200Smm	assertMakeDir("d1/d2", 0755);
961231200Smm	assertMakeDir("d1/d2/d3", 0755);
962231200Smm	assertMakeDir("d2", 0755);
963231200Smm	assertMakeFile("d2/file1", 0644, "d2/file1");
964231200Smm	assertMakeSymlink("d1/d2/ld1", "../../d1");
965231200Smm	assertMakeSymlink("d1/d2/ld2", "../../d2");
966231200Smm	assertChdir("..");
967231200Smm
968231200Smm	assert((ae = archive_entry_new()) != NULL);
969231200Smm	assert((a = archive_read_disk_new()) != NULL);
970231200Smm	assertEqualIntA(a, ARCHIVE_OK,
971231200Smm	    archive_read_disk_set_symlink_logical(a));
972231200Smm
973231200Smm	/*
974231200Smm	 * Specified file is a symbolic link file.
975231200Smm	 */
976231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l2/d1"));
977231200Smm	file_count = 6;
978231200Smm
979231200Smm	while (file_count--) {
980231200Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
981231200Smm		if (strcmp(archive_entry_pathname(ae), "l2/d1") == 0) {
982231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
983231200Smm		} else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2") == 0) {
984231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
985231200Smm		} else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2/d3") == 0) {
986231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
987231200Smm		} else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2/ld1") == 0) {
988231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
989231200Smm		} else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2/ld2") == 0) {
990231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
991231200Smm		} else if (strcmp(archive_entry_pathname(ae),
992231200Smm		    "l2/d1/d2/ld2/file1") == 0) {
993231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
994231200Smm			assertEqualInt(archive_entry_size(ae), 8);
995231200Smm			assertEqualIntA(a, ARCHIVE_OK,
996231200Smm			    archive_read_data_block(a, &p, &size, &offset));
997231200Smm			assertEqualInt((int)size, 8);
998231200Smm			assertEqualInt((int)offset, 0);
999231200Smm			assertEqualMem(p, "d2/file1", 8);
1000231200Smm			assertEqualInt(ARCHIVE_EOF,
1001231200Smm			    archive_read_data_block(a, &p, &size, &offset));
1002231200Smm			assertEqualInt((int)size, 0);
1003231200Smm			assertEqualInt((int)offset, 8);
1004231200Smm		}
1005231200Smm		if (archive_entry_filetype(ae) == AE_IFDIR) {
1006231200Smm			/* Descend into the current object */
1007231200Smm			assertEqualIntA(a, ARCHIVE_OK,
1008231200Smm			    archive_read_disk_descend(a));
1009231200Smm		}
1010231200Smm	}
1011231200Smm	/* There is no entry. */
1012231200Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1013231200Smm	/* Destroy the disk object. */
1014231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1015231200Smm	archive_entry_free(ae);
1016231200Smm}
1017231200Smm
1018231200Smmstatic void
1019231200Smmtest_restore_atime(void)
1020231200Smm{
1021231200Smm	struct archive *a;
1022231200Smm	struct archive_entry *ae;
1023231200Smm	const void *p;
1024231200Smm	size_t size;
1025231200Smm	int64_t offset;
1026231200Smm	int file_count;
1027231200Smm
1028231200Smm	if (!atimeIsUpdated()) {
1029231200Smm		skipping("Can't test restoring atime on this filesystem");
1030231200Smm		return;
1031231200Smm	}
1032231200Smm
1033231200Smm	assertMakeDir("at", 0755);
1034231200Smm	assertMakeFile("at/f1", 0644, "0123456789");
1035231200Smm	assertMakeFile("at/f2", 0644, "hello world");
1036231200Smm	assertMakeFile("at/fe", 0644, NULL);
1037231200Smm	assertUtimes("at/f1", 886600, 0, 886600, 0);
1038231200Smm	assertUtimes("at/f2", 886611, 0, 886611, 0);
1039231200Smm	assertUtimes("at/fe", 886611, 0, 886611, 0);
1040231200Smm	assertUtimes("at", 886622, 0, 886622, 0);
1041231200Smm	file_count = 4;
1042231200Smm
1043231200Smm	assert((ae = archive_entry_new()) != NULL);
1044231200Smm	assert((a = archive_read_disk_new()) != NULL);
1045231200Smm
1046231200Smm	/*
1047231200Smm	 * Test1: Traversals without archive_read_disk_set_atime_restored().
1048231200Smm	 */
1049231200Smm	failure("Directory traversals should work as well");
1050231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1051231200Smm	while (file_count--) {
1052231200Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1053231200Smm		if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1054231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1055231200Smm		} else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1056231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1057231200Smm			assertEqualInt(archive_entry_size(ae), 10);
1058231200Smm			assertEqualIntA(a, ARCHIVE_OK,
1059231200Smm			    archive_read_data_block(a, &p, &size, &offset));
1060231200Smm			assertEqualInt((int)size, 10);
1061231200Smm			assertEqualInt((int)offset, 0);
1062231200Smm			assertEqualMem(p, "0123456789", 10);
1063231200Smm			assertEqualInt(ARCHIVE_EOF,
1064231200Smm			    archive_read_data_block(a, &p, &size, &offset));
1065231200Smm			assertEqualInt((int)size, 0);
1066231200Smm			assertEqualInt((int)offset, 10);
1067231200Smm		} else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1068231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1069231200Smm			assertEqualInt(archive_entry_size(ae), 11);
1070231200Smm			assertEqualIntA(a, ARCHIVE_OK,
1071231200Smm			    archive_read_data_block(a, &p, &size, &offset));
1072231200Smm			assertEqualInt((int)size, 11);
1073231200Smm			assertEqualInt((int)offset, 0);
1074231200Smm			assertEqualMem(p, "hello world", 11);
1075231200Smm			assertEqualInt(ARCHIVE_EOF,
1076231200Smm			    archive_read_data_block(a, &p, &size, &offset));
1077231200Smm			assertEqualInt((int)size, 0);
1078231200Smm			assertEqualInt((int)offset, 11);
1079231200Smm		} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1080231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1081231200Smm			assertEqualInt(archive_entry_size(ae), 0);
1082231200Smm		}
1083231200Smm		if (archive_entry_filetype(ae) == AE_IFDIR) {
1084231200Smm			/* Descend into the current object */
1085231200Smm			assertEqualIntA(a, ARCHIVE_OK,
1086231200Smm			    archive_read_disk_descend(a));
1087231200Smm		}
1088231200Smm	}
1089231200Smm	/* There is no entry. */
1090231200Smm	failure("There must be no entry");
1091231200Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1092231200Smm
1093299529Smm	/* On FreeBSD (and likely other systems), atime on
1094299529Smm	   dirs does not change when it is read. */
1095299529Smm	/* failure("Atime should be restored"); */
1096299529Smm	/* assertFileAtimeRecent("at"); */
1097238856Smm	failure("Atime should be restored");
1098231200Smm	assertFileAtimeRecent("at/f1");
1099238856Smm	failure("Atime should be restored");
1100231200Smm	assertFileAtimeRecent("at/f2");
1101238856Smm	failure("The atime of a empty file should not be changed");
1102231200Smm	assertFileAtime("at/fe", 886611, 0);
1103231200Smm
1104231200Smm	/* Close the disk object. */
1105231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1106231200Smm
1107231200Smm	/*
1108231200Smm	 * Test2: Traversals with archive_read_disk_set_atime_restored().
1109231200Smm	 */
1110231200Smm	assertUtimes("at/f1", 886600, 0, 886600, 0);
1111231200Smm	assertUtimes("at/f2", 886611, 0, 886611, 0);
1112231200Smm	assertUtimes("at/fe", 886611, 0, 886611, 0);
1113231200Smm	assertUtimes("at", 886622, 0, 886622, 0);
1114231200Smm	file_count = 4;
1115231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a));
1116231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1117231200Smm
1118231200Smm	failure("Directory traversals should work as well");
1119231200Smm	while (file_count--) {
1120231200Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1121231200Smm		if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1122231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1123231200Smm		} else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1124231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1125231200Smm			assertEqualInt(archive_entry_size(ae), 10);
1126231200Smm			assertEqualIntA(a, ARCHIVE_OK,
1127231200Smm			    archive_read_data_block(a, &p, &size, &offset));
1128231200Smm			assertEqualInt((int)size, 10);
1129231200Smm			assertEqualInt((int)offset, 0);
1130231200Smm			assertEqualMem(p, "0123456789", 10);
1131231200Smm			assertEqualInt(ARCHIVE_EOF,
1132231200Smm			    archive_read_data_block(a, &p, &size, &offset));
1133231200Smm			assertEqualInt((int)size, 0);
1134231200Smm			assertEqualInt((int)offset, 10);
1135231200Smm		} else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1136231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1137231200Smm			assertEqualInt(archive_entry_size(ae), 11);
1138231200Smm			assertEqualIntA(a, ARCHIVE_OK,
1139231200Smm			    archive_read_data_block(a, &p, &size, &offset));
1140231200Smm			assertEqualInt((int)size, 11);
1141231200Smm			assertEqualInt((int)offset, 0);
1142231200Smm			assertEqualMem(p, "hello world", 11);
1143231200Smm			assertEqualInt(ARCHIVE_EOF,
1144231200Smm			    archive_read_data_block(a, &p, &size, &offset));
1145231200Smm			assertEqualInt((int)size, 0);
1146231200Smm			assertEqualInt((int)offset, 11);
1147231200Smm		} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1148231200Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1149231200Smm			assertEqualInt(archive_entry_size(ae), 0);
1150231200Smm		}
1151231200Smm		if (archive_entry_filetype(ae) == AE_IFDIR) {
1152231200Smm			/* Descend into the current object */
1153231200Smm			assertEqualIntA(a, ARCHIVE_OK,
1154231200Smm			    archive_read_disk_descend(a));
1155231200Smm		}
1156231200Smm	}
1157231200Smm	/* There is no entry. */
1158231200Smm	failure("There must be no entry");
1159231200Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1160231200Smm
1161238856Smm	failure("Atime should be restored");
1162231200Smm	assertFileAtime("at", 886622, 0);
1163238856Smm	failure("Atime should be restored");
1164231200Smm	assertFileAtime("at/f1", 886600, 0);
1165238856Smm	failure("Atime should be restored");
1166231200Smm	assertFileAtime("at/f2", 886611, 0);
1167238856Smm	failure("The atime of a empty file should not be changed");
1168231200Smm	assertFileAtime("at/fe", 886611, 0);
1169231200Smm
1170238856Smm	/* Close the disk object. */
1171238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1172238856Smm
1173238856Smm	/*
1174238856Smm	 * Test3: Traversals with archive_read_disk_set_atime_restored() but
1175238856Smm	 * no data read as a listing.
1176238856Smm	 */
1177238856Smm	assertUtimes("at/f1", 886600, 0, 886600, 0);
1178238856Smm	assertUtimes("at/f2", 886611, 0, 886611, 0);
1179238856Smm	assertUtimes("at/fe", 886611, 0, 886611, 0);
1180238856Smm	assertUtimes("at", 886622, 0, 886622, 0);
1181238856Smm	file_count = 4;
1182238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a));
1183238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1184238856Smm
1185238856Smm	failure("Directory traversals should work as well");
1186238856Smm	while (file_count--) {
1187238856Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1188238856Smm		if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1189238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1190238856Smm		} else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1191238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1192238856Smm			assertEqualInt(archive_entry_size(ae), 10);
1193238856Smm		} else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1194238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1195238856Smm			assertEqualInt(archive_entry_size(ae), 11);
1196238856Smm		} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1197238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1198238856Smm			assertEqualInt(archive_entry_size(ae), 0);
1199238856Smm		}
1200238856Smm		if (archive_entry_filetype(ae) == AE_IFDIR) {
1201238856Smm			/* Descend into the current object */
1202238856Smm			assertEqualIntA(a, ARCHIVE_OK,
1203238856Smm			    archive_read_disk_descend(a));
1204238856Smm		}
1205238856Smm	}
1206238856Smm	/* There is no entry. */
1207238856Smm	failure("There must be no entry");
1208238856Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1209238856Smm
1210238856Smm	failure("Atime should be restored");
1211238856Smm	assertFileAtime("at", 886622, 0);
1212238856Smm	failure("Atime should be restored");
1213238856Smm	assertFileAtime("at/f1", 886600, 0);
1214238856Smm	failure("Atime should be restored");
1215238856Smm	assertFileAtime("at/f2", 886611, 0);
1216238856Smm	failure("The atime of a empty file should not be changed");
1217238856Smm	assertFileAtime("at/fe", 886611, 0);
1218238856Smm
1219238856Smm	if (!canNodump()) {
1220238856Smm		/* Destroy the disk object. */
1221238856Smm		assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1222238856Smm		archive_entry_free(ae);
1223238856Smm		skipping("Can't test atime with nodump on this filesystem");
1224238856Smm		return;
1225238856Smm	}
1226238856Smm
1227238856Smm	/* Close the disk object. */
1228238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1229238856Smm
1230238856Smm	/*
1231238856Smm	 * Test4: Traversals with archive_read_disk_set_atime_restored() and
1232238856Smm	 * archive_read_disk_honor_nodump().
1233238856Smm	 */
1234238856Smm	assertNodump("at/f1");
1235238856Smm	assertNodump("at/f2");
1236238856Smm	assertUtimes("at/f1", 886600, 0, 886600, 0);
1237238856Smm	assertUtimes("at/f2", 886611, 0, 886611, 0);
1238238856Smm	assertUtimes("at/fe", 886611, 0, 886611, 0);
1239238856Smm	assertUtimes("at", 886622, 0, 886622, 0);
1240238856Smm	file_count = 2;
1241238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a,
1242238856Smm		ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP));
1243238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1244238856Smm
1245238856Smm	failure("Directory traversals should work as well");
1246238856Smm	while (file_count--) {
1247238856Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1248238856Smm		if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1249238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1250238856Smm		} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1251238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1252238856Smm			assertEqualInt(archive_entry_size(ae), 0);
1253238856Smm		}
1254238856Smm		if (archive_entry_filetype(ae) == AE_IFDIR) {
1255238856Smm			/* Descend into the current object */
1256238856Smm			assertEqualIntA(a, ARCHIVE_OK,
1257238856Smm			    archive_read_disk_descend(a));
1258238856Smm		}
1259238856Smm	}
1260238856Smm	/* There is no entry. */
1261238856Smm	failure("There must be no entry");
1262238856Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1263238856Smm
1264238856Smm	failure("Atime should be restored");
1265238856Smm	assertFileAtime("at", 886622, 0);
1266238856Smm	failure("Atime should be restored");
1267238856Smm	assertFileAtime("at/f1", 886600, 0);
1268238856Smm	failure("Atime should be restored");
1269238856Smm	assertFileAtime("at/f2", 886611, 0);
1270238856Smm	failure("The atime of a empty file should not be changed");
1271238856Smm	assertFileAtime("at/fe", 886611, 0);
1272238856Smm
1273231200Smm	/* Destroy the disk object. */
1274231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1275231200Smm	archive_entry_free(ae);
1276231200Smm}
1277231200Smm
1278238856Smmstatic int
1279238856Smmmetadata_filter(struct archive *a, void *data, struct archive_entry *ae)
1280238856Smm{
1281238856Smm	(void)data; /* UNUSED */
1282238856Smm
1283238856Smm	failure("CTime should be set");
1284238856Smm	assertEqualInt(8, archive_entry_ctime_is_set(ae));
1285238856Smm	failure("MTime should be set");
1286238856Smm	assertEqualInt(16, archive_entry_mtime_is_set(ae));
1287238856Smm
1288238856Smm	if (archive_entry_mtime(ae) < 886611)
1289238856Smm		return (0);
1290238856Smm	if (archive_read_disk_can_descend(a)) {
1291238856Smm		/* Descend into the current object */
1292238856Smm		failure("archive_read_disk_can_descend should work"
1293238856Smm			" in metadata filter");
1294238856Smm		assertEqualIntA(a, 1, archive_read_disk_can_descend(a));
1295238856Smm		failure("archive_read_disk_descend should work"
1296238856Smm			" in metadata filter");
1297238856Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a));
1298238856Smm	}
1299238856Smm	return (1);
1300238856Smm}
1301238856Smm
1302238856Smmstatic void
1303238856Smmtest_callbacks(void)
1304238856Smm{
1305238856Smm	struct archive *a;
1306238856Smm	struct archive *m;
1307238856Smm	struct archive_entry *ae;
1308238856Smm	const void *p;
1309238856Smm	size_t size;
1310238856Smm	int64_t offset;
1311238856Smm	int file_count;
1312238856Smm
1313238856Smm	assertMakeDir("cb", 0755);
1314238856Smm	assertMakeFile("cb/f1", 0644, "0123456789");
1315238856Smm	assertMakeFile("cb/f2", 0644, "hello world");
1316238856Smm	assertMakeFile("cb/fe", 0644, NULL);
1317238856Smm	assertUtimes("cb/f1", 886600, 0, 886600, 0);
1318238856Smm	assertUtimes("cb/f2", 886611, 0, 886611, 0);
1319238856Smm	assertUtimes("cb/fe", 886611, 0, 886611, 0);
1320238856Smm	assertUtimes("cb", 886622, 0, 886622, 0);
1321238856Smm
1322238856Smm	assert((ae = archive_entry_new()) != NULL);
1323238856Smm	if (assert((a = archive_read_disk_new()) != NULL)) {
1324238856Smm		archive_entry_free(ae);
1325238856Smm		return;
1326238856Smm	}
1327238856Smm	if (assert((m = archive_match_new()) != NULL)) {
1328238856Smm		archive_entry_free(ae);
1329238856Smm		archive_read_free(a);
1330238856Smm		return;
1331238856Smm	}
1332238856Smm
1333238856Smm	/*
1334238856Smm	 * Test1: Traversals with a name filter.
1335238856Smm	 */
1336238856Smm	file_count = 3;
1337238856Smm	assertEqualIntA(m, ARCHIVE_OK,
1338238856Smm	    archive_match_exclude_pattern(m, "cb/f2"));
1339238856Smm	assertEqualIntA(a, ARCHIVE_OK,
1340238856Smm	    archive_read_disk_set_matching(a, m, NULL, NULL));
1341238856Smm	failure("Directory traversals should work as well");
1342238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
1343238856Smm	while (file_count--) {
1344238856Smm		archive_entry_clear(ae);
1345238856Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1346238856Smm		failure("File 'cb/f2' should be exclueded");
1347238856Smm		assert(strcmp(archive_entry_pathname(ae), "cb/f2") != 0);
1348238856Smm		if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
1349238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1350238856Smm		} else if (strcmp(archive_entry_pathname(ae), "cb/f1") == 0) {
1351238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1352238856Smm			assertEqualInt(archive_entry_size(ae), 10);
1353238856Smm			assertEqualIntA(a, ARCHIVE_OK,
1354238856Smm			    archive_read_data_block(a, &p, &size, &offset));
1355238856Smm			assertEqualInt((int)size, 10);
1356238856Smm			assertEqualInt((int)offset, 0);
1357238856Smm			assertEqualMem(p, "0123456789", 10);
1358238856Smm			assertEqualInt(ARCHIVE_EOF,
1359238856Smm			    archive_read_data_block(a, &p, &size, &offset));
1360238856Smm			assertEqualInt((int)size, 0);
1361238856Smm			assertEqualInt((int)offset, 10);
1362238856Smm		} else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
1363238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1364238856Smm			assertEqualInt(archive_entry_size(ae), 0);
1365238856Smm		}
1366238856Smm		if (archive_read_disk_can_descend(a)) {
1367238856Smm			/* Descend into the current object */
1368238856Smm			assertEqualIntA(a, ARCHIVE_OK,
1369238856Smm			    archive_read_disk_descend(a));
1370238856Smm		}
1371238856Smm	}
1372238856Smm	/* There is no entry. */
1373238856Smm	failure("There should be no entry");
1374238856Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1375238856Smm
1376238856Smm	/* Close the disk object. */
1377238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1378238856Smm
1379238856Smm	/*
1380238856Smm	 * Test2: Traversals with a metadata filter.
1381238856Smm	 */
1382238856Smm	assertUtimes("cb/f1", 886600, 0, 886600, 0);
1383238856Smm	assertUtimes("cb/f2", 886611, 0, 886611, 0);
1384238856Smm	assertUtimes("cb/fe", 886611, 0, 886611, 0);
1385238856Smm	assertUtimes("cb", 886622, 0, 886622, 0);
1386238856Smm	file_count = 3;
1387238856Smm	assertEqualIntA(a, ARCHIVE_OK,
1388238856Smm	    archive_read_disk_set_metadata_filter_callback(a, metadata_filter,
1389238856Smm		    NULL));
1390238856Smm	failure("Directory traversals should work as well");
1391238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
1392238856Smm
1393238856Smm	while (file_count--) {
1394238856Smm		archive_entry_clear(ae);
1395238856Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1396238856Smm		failure("File 'cb/f1' should be exclueded");
1397238856Smm		assert(strcmp(archive_entry_pathname(ae), "cb/f1") != 0);
1398238856Smm		if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
1399238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1400238856Smm		} else if (strcmp(archive_entry_pathname(ae), "cb/f2") == 0) {
1401238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1402238856Smm			assertEqualInt(archive_entry_size(ae), 11);
1403238856Smm			assertEqualIntA(a, ARCHIVE_OK,
1404238856Smm			    archive_read_data_block(a, &p, &size, &offset));
1405238856Smm			assertEqualInt((int)size, 11);
1406238856Smm			assertEqualInt((int)offset, 0);
1407238856Smm			assertEqualMem(p, "hello world", 11);
1408238856Smm			assertEqualInt(ARCHIVE_EOF,
1409238856Smm			    archive_read_data_block(a, &p, &size, &offset));
1410238856Smm			assertEqualInt((int)size, 0);
1411238856Smm			assertEqualInt((int)offset, 11);
1412238856Smm		} else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
1413238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1414238856Smm			assertEqualInt(archive_entry_size(ae), 0);
1415238856Smm		}
1416238856Smm	}
1417238856Smm	/* There is no entry. */
1418238856Smm	failure("There should be no entry");
1419238856Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1420238856Smm
1421238856Smm	/* Destroy the disk object. */
1422238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1423238856Smm	assertEqualInt(ARCHIVE_OK, archive_match_free(m));
1424238856Smm	archive_entry_free(ae);
1425238856Smm}
1426238856Smm
1427238856Smmstatic void
1428238856Smmtest_nodump(void)
1429238856Smm{
1430238856Smm	struct archive *a;
1431238856Smm	struct archive_entry *ae;
1432238856Smm	const void *p;
1433238856Smm	size_t size;
1434238856Smm	int64_t offset;
1435238856Smm	int file_count;
1436238856Smm
1437238856Smm	if (!canNodump()) {
1438238856Smm		skipping("Can't test nodump on this filesystem");
1439238856Smm		return;
1440238856Smm	}
1441238856Smm
1442238856Smm	assertMakeDir("nd", 0755);
1443238856Smm	assertMakeFile("nd/f1", 0644, "0123456789");
1444238856Smm	assertMakeFile("nd/f2", 0644, "hello world");
1445238856Smm	assertMakeFile("nd/fe", 0644, NULL);
1446238856Smm	assertNodump("nd/f2");
1447238856Smm	assertUtimes("nd/f1", 886600, 0, 886600, 0);
1448238856Smm	assertUtimes("nd/f2", 886611, 0, 886611, 0);
1449238856Smm	assertUtimes("nd/fe", 886611, 0, 886611, 0);
1450238856Smm	assertUtimes("nd", 886622, 0, 886622, 0);
1451238856Smm
1452238856Smm	assert((ae = archive_entry_new()) != NULL);
1453238856Smm	assert((a = archive_read_disk_new()) != NULL);
1454238856Smm
1455238856Smm	/*
1456238856Smm	 * Test1: Traversals without archive_read_disk_honor_nodump().
1457238856Smm	 */
1458238856Smm	failure("Directory traversals should work as well");
1459238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
1460238856Smm
1461238856Smm	file_count = 4;
1462238856Smm	while (file_count--) {
1463238856Smm		archive_entry_clear(ae);
1464238856Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1465238856Smm		if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
1466238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1467238856Smm		} else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) {
1468238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1469238856Smm			assertEqualInt(archive_entry_size(ae), 10);
1470238856Smm			assertEqualIntA(a, ARCHIVE_OK,
1471238856Smm			    archive_read_data_block(a, &p, &size, &offset));
1472238856Smm			assertEqualInt((int)size, 10);
1473238856Smm			assertEqualInt((int)offset, 0);
1474238856Smm			assertEqualMem(p, "0123456789", 10);
1475238856Smm			assertEqualInt(ARCHIVE_EOF,
1476238856Smm			    archive_read_data_block(a, &p, &size, &offset));
1477238856Smm			assertEqualInt((int)size, 0);
1478238856Smm			assertEqualInt((int)offset, 10);
1479238856Smm		} else if (strcmp(archive_entry_pathname(ae), "nd/f2") == 0) {
1480238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1481238856Smm			assertEqualInt(archive_entry_size(ae), 11);
1482238856Smm			assertEqualIntA(a, ARCHIVE_OK,
1483238856Smm			    archive_read_data_block(a, &p, &size, &offset));
1484238856Smm			assertEqualInt((int)size, 11);
1485238856Smm			assertEqualInt((int)offset, 0);
1486238856Smm			assertEqualMem(p, "hello world", 11);
1487238856Smm			assertEqualInt(ARCHIVE_EOF,
1488238856Smm			    archive_read_data_block(a, &p, &size, &offset));
1489238856Smm			assertEqualInt((int)size, 0);
1490238856Smm			assertEqualInt((int)offset, 11);
1491238856Smm		} else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
1492238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1493238856Smm			assertEqualInt(archive_entry_size(ae), 0);
1494238856Smm		}
1495238856Smm		if (archive_read_disk_can_descend(a)) {
1496238856Smm			/* Descend into the current object */
1497238856Smm			assertEqualIntA(a, ARCHIVE_OK,
1498238856Smm			    archive_read_disk_descend(a));
1499238856Smm		}
1500238856Smm	}
1501238856Smm	/* There is no entry. */
1502238856Smm	failure("There should be no entry");
1503238856Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1504238856Smm
1505238856Smm	/* Close the disk object. */
1506238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1507238856Smm
1508238856Smm	/*
1509238856Smm	 * Test2: Traversals with archive_read_disk_honor_nodump().
1510238856Smm	 */
1511238856Smm	assertUtimes("nd/f1", 886600, 0, 886600, 0);
1512238856Smm	assertUtimes("nd/f2", 886611, 0, 886611, 0);
1513238856Smm	assertUtimes("nd/fe", 886611, 0, 886611, 0);
1514238856Smm	assertUtimes("nd", 886622, 0, 886622, 0);
1515238856Smm
1516238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a,
1517238856Smm		ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP));
1518238856Smm	failure("Directory traversals should work as well");
1519238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
1520238856Smm
1521238856Smm	file_count = 3;
1522238856Smm	while (file_count--) {
1523238856Smm		archive_entry_clear(ae);
1524238856Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1525238856Smm		failure("File 'nd/f2' should be exclueded");
1526238856Smm		assert(strcmp(archive_entry_pathname(ae), "nd/f2") != 0);
1527238856Smm		if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
1528238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1529238856Smm		} else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) {
1530238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1531238856Smm			assertEqualInt(archive_entry_size(ae), 10);
1532238856Smm			assertEqualIntA(a, ARCHIVE_OK,
1533238856Smm			    archive_read_data_block(a, &p, &size, &offset));
1534238856Smm			assertEqualInt((int)size, 10);
1535238856Smm			assertEqualInt((int)offset, 0);
1536238856Smm			assertEqualMem(p, "0123456789", 10);
1537238856Smm			assertEqualInt(ARCHIVE_EOF,
1538238856Smm			    archive_read_data_block(a, &p, &size, &offset));
1539238856Smm			assertEqualInt((int)size, 0);
1540238856Smm			assertEqualInt((int)offset, 10);
1541238856Smm		} else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
1542238856Smm			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1543238856Smm			assertEqualInt(archive_entry_size(ae), 0);
1544238856Smm		}
1545238856Smm		if (archive_read_disk_can_descend(a)) {
1546238856Smm			/* Descend into the current object */
1547238856Smm			assertEqualIntA(a, ARCHIVE_OK,
1548238856Smm			    archive_read_disk_descend(a));
1549238856Smm		}
1550238856Smm	}
1551238856Smm	/* There is no entry. */
1552238856Smm	failure("There should be no entry");
1553238856Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1554238856Smm
1555238856Smm	failure("Atime should be restored");
1556238856Smm	assertFileAtime("nd/f2", 886611, 0);
1557238856Smm
1558238856Smm	/* Destroy the disk object. */
1559238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1560238856Smm	archive_entry_free(ae);
1561238856Smm}
1562238856Smm
1563231200SmmDEFINE_TEST(test_read_disk_directory_traversals)
1564231200Smm{
1565231200Smm	/* Basic test. */
1566231200Smm	test_basic();
1567231200Smm	/* Test hybird mode; follow symlink initially, then not. */
1568231200Smm	test_symlink_hybrid();
1569231200Smm	/* Test logcal mode; follow all symlinks. */
1570231200Smm	test_symlink_logical();
1571231200Smm	/* Test logcal mode; prevent loop in symlinks. */
1572231200Smm	test_symlink_logical_loop();
1573231200Smm	/* Test to restore atime. */
1574231200Smm	test_restore_atime();
1575238856Smm	/* Test callbacks. */
1576238856Smm	test_callbacks();
1577238856Smm	/* Test nodump. */
1578238856Smm	test_nodump();
1579231200Smm}
1580