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  */
38 static int
39 atimeIsUpdated(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 
82 static void
83 test_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 
575 static void
576 test_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 
732 static void
733 test_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 
962 static void
963 test_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 
1041 static void
1042 test_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 
1308 static int
1309 metadata_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 
1332 static void
1333 test_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 
1464 static void
1465 test_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 
1600 static void
1601 test_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 #if defined(O_PATH) || defined(O_SEARCH) || \
1612  (defined(__FreeBSD__) && defined(O_EXEC))
1613 	const char *ignore_traversals_test4;
1614 
1615 	ignore_traversals_test4 = getenv("IGNORE_TRAVERSALS_TEST4");
1616 #endif
1617 
1618 	assertMakeDir("lock", 0311);
1619 	assertMakeDir("lock/dir1", 0755);
1620 	assertMakeFile("lock/dir1/f1", 0644, "0123456789");
1621 	assertMakeDir("lock/lock2", 0311);
1622 	assertMakeDir("lock/lock2/dir1", 0755);
1623 	assertMakeFile("lock/lock2/dir1/f1", 0644, "0123456789");
1624 
1625 	assert((ae = archive_entry_new()) != NULL);
1626 	assert((a = archive_read_disk_new()) != NULL);
1627 
1628 	/*
1629 	 * Test1: Traverse lock/dir1 as .
1630 	 */
1631 	assertChdir("lock/dir1");
1632 
1633 	failure("Directory traversals should work as well");
1634 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "."));
1635 
1636 	file_count = 2;
1637 	match_count = 0;
1638 	while (file_count--) {
1639 		archive_entry_clear(ae);
1640 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1641 		if (strcmp(archive_entry_pathname(ae), ".") == 0) {
1642 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1643 			++match_count;
1644 		} else if (strcmp(archive_entry_pathname(ae), "./f1") == 0) {
1645 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1646 			assertEqualInt(archive_entry_size(ae), 10);
1647 			assertEqualIntA(a, ARCHIVE_OK,
1648 			    archive_read_data_block(a, &p, &size, &offset));
1649 			assertEqualInt((int)size, 10);
1650 			assertEqualInt((int)offset, 0);
1651 			assertEqualMem(p, "0123456789", 10);
1652 			assertEqualInt(ARCHIVE_EOF,
1653 			    archive_read_data_block(a, &p, &size, &offset));
1654 			assertEqualInt((int)size, 0);
1655 			assertEqualInt((int)offset, 10);
1656 			++match_count;
1657 		}
1658 		if (archive_read_disk_can_descend(a)) {
1659 			/* Descend into the current object */
1660 			assertEqualIntA(a, ARCHIVE_OK,
1661 			    archive_read_disk_descend(a));
1662 		}
1663 	}
1664 	failure("Did not match expected filenames");
1665 	assertEqualInt(match_count, 2);
1666 	/*
1667 	 * There is no entry. This will however fail if the directory traverse
1668 	 * tries to ascend past the initial directory, since it lacks permission
1669 	 * to do so.
1670 	 */
1671 	failure("There should be no entry and no error");
1672 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1673 
1674 	/* Close the disk object. */
1675 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1676 
1677 	assertChdir("../..");
1678 
1679 	/*
1680 	 * Test2: Traverse lock/dir1 directly
1681 	 */
1682 	failure("Directory traversals should work as well");
1683 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock/dir1"));
1684 
1685 	file_count = 2;
1686 	match_count = 0;
1687 	while (file_count--) {
1688 		archive_entry_clear(ae);
1689 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1690 		if (strcmp(archive_entry_pathname(ae), "lock/dir1") == 0) {
1691 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1692 			++match_count;
1693 		} else if (strcmp(archive_entry_pathname(ae), "lock/dir1/f1") == 0) {
1694 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1695 			assertEqualInt(archive_entry_size(ae), 10);
1696 			assertEqualIntA(a, ARCHIVE_OK,
1697 			    archive_read_data_block(a, &p, &size, &offset));
1698 			assertEqualInt((int)size, 10);
1699 			assertEqualInt((int)offset, 0);
1700 			assertEqualMem(p, "0123456789", 10);
1701 			assertEqualInt(ARCHIVE_EOF,
1702 			    archive_read_data_block(a, &p, &size, &offset));
1703 			assertEqualInt((int)size, 0);
1704 			assertEqualInt((int)offset, 10);
1705 			++match_count;
1706 		}
1707 		if (archive_read_disk_can_descend(a)) {
1708 			/* Descend into the current object */
1709 			assertEqualIntA(a, ARCHIVE_OK,
1710 			    archive_read_disk_descend(a));
1711 		}
1712 	}
1713 	failure("Did not match expected filenames");
1714 	assertEqualInt(match_count, 2);
1715 	/*
1716 	 * There is no entry. This will however fail if the directory traverse
1717 	 * tries to ascend past the initial directory, since it lacks permission
1718 	 * to do so.
1719 	 */
1720 	failure("There should be no entry and no error");
1721 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1722 
1723 	/* Close the disk object. */
1724 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1725 
1726 	/*
1727 	 * Test3: Traverse lock/dir1/.
1728 	 */
1729 	failure("Directory traversals should work as well");
1730 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock/dir1/."));
1731 
1732 	file_count = 2;
1733 	match_count = 0;
1734 	while (file_count--) {
1735 		archive_entry_clear(ae);
1736 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1737 		if (strcmp(archive_entry_pathname(ae), "lock/dir1/.") == 0) {
1738 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1739 			++match_count;
1740 		} else if (strcmp(archive_entry_pathname(ae), "lock/dir1/./f1") == 0) {
1741 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1742 			assertEqualInt(archive_entry_size(ae), 10);
1743 			assertEqualIntA(a, ARCHIVE_OK,
1744 			    archive_read_data_block(a, &p, &size, &offset));
1745 			assertEqualInt((int)size, 10);
1746 			assertEqualInt((int)offset, 0);
1747 			assertEqualMem(p, "0123456789", 10);
1748 			assertEqualInt(ARCHIVE_EOF,
1749 			    archive_read_data_block(a, &p, &size, &offset));
1750 			assertEqualInt((int)size, 0);
1751 			assertEqualInt((int)offset, 10);
1752 			++match_count;
1753 		}
1754 		if (archive_read_disk_can_descend(a)) {
1755 			/* Descend into the current object */
1756 			assertEqualIntA(a, ARCHIVE_OK,
1757 			    archive_read_disk_descend(a));
1758 		}
1759 	}
1760 	failure("Did not match expected filenames");
1761 	assertEqualInt(match_count, 2);
1762 	/*
1763 	 * There is no entry. This will however fail if the directory traverse
1764 	 * tries to ascend past the initial directory, since it lacks permission
1765 	 * to do so.
1766 	 */
1767 	failure("There should be no entry and no error");
1768 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1769 
1770 	/* Close the disk object. */
1771 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1772 
1773 	/*
1774 	 * Test4: Traverse lock/lock2/dir1 from inside lock.
1775 	 *
1776 	 * This test is expected to fail on platforms with no O_EXEC or
1777 	 * equivalent (e.g. O_PATH on Linux or O_SEARCH on SunOS), because
1778 	 * the current traversal code can't handle the case where it can't
1779 	 * obtain an open fd for the initial current directory. We need to
1780 	 * check that condition here, because if O_EXEC _does_ exist, we don't
1781 	 * want to overlook any failure.
1782 	 */
1783 	assertChdir("lock");
1784 
1785 	failure("Directory traversals should work as well");
1786 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock2/dir1"));
1787 
1788 	archive_entry_clear(ae);
1789 	r = archive_read_next_header2(a, ae);
1790 	if (r == ARCHIVE_FAILED) {
1791 #if defined(O_PATH) || defined(O_SEARCH) || \
1792  (defined(__FreeBSD__) && defined(O_EXEC))
1793 		if (ignore_traversals_test4 == NULL)
1794 			assertEqualIntA(a, ARCHIVE_OK, r);
1795 #endif
1796 		/* Close the disk object. */
1797 		archive_read_close(a);
1798 	} else {
1799 		file_count = 2;
1800 		match_count = 0;
1801 		while (file_count--) {
1802 			if (file_count == 0)
1803 				assertEqualIntA(a, ARCHIVE_OK,
1804 				    archive_read_next_header2(a, ae));
1805 			if (strcmp(archive_entry_pathname(ae),
1806 				"lock2/dir1") == 0) {
1807 				assertEqualInt(archive_entry_filetype(ae),
1808 				    AE_IFDIR);
1809 				++match_count;
1810 			} else if (strcmp(archive_entry_pathname(ae),
1811 				"lock2/dir1/f1") == 0) {
1812 				assertEqualInt(archive_entry_filetype(ae),
1813 				    AE_IFREG);
1814 				assertEqualInt(archive_entry_size(ae), 10);
1815 				assertEqualIntA(a, ARCHIVE_OK,
1816 				    archive_read_data_block(a, &p, &size,
1817 					&offset));
1818 				assertEqualInt((int)size, 10);
1819 				assertEqualInt((int)offset, 0);
1820 				assertEqualMem(p, "0123456789", 10);
1821 				assertEqualInt(ARCHIVE_EOF,
1822 				    archive_read_data_block(a, &p, &size,
1823 					&offset));
1824 				assertEqualInt((int)size, 0);
1825 				assertEqualInt((int)offset, 10);
1826 				++match_count;
1827 			}
1828 			if (archive_read_disk_can_descend(a)) {
1829 				/* Descend into the current object */
1830 				assertEqualIntA(a, ARCHIVE_OK,
1831 				    archive_read_disk_descend(a));
1832 			}
1833 		}
1834 		failure("Did not match expected filenames");
1835 		assertEqualInt(match_count, 2);
1836 		/*
1837 		 * There is no entry. This will however fail if the directory
1838 		 * traverse tries to ascend past the initial directory, since
1839 		 * it lacks permission to do so.
1840 		 */
1841 		failure("There should be no entry and no error");
1842 		assertEqualIntA(a, ARCHIVE_EOF,
1843 		    archive_read_next_header2(a, ae));
1844 
1845 		/* Close the disk object. */
1846 		assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1847 	}
1848 
1849 	assertChdir("..");
1850 	assertChmod("lock", 0755);
1851 	assertChmod("lock/lock2", 0755);
1852 
1853 	/* Destroy the disk object. */
1854 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1855 	archive_entry_free(ae);
1856 }
1857 
1858 DEFINE_TEST(test_read_disk_directory_traversals)
1859 {
1860 	/* Basic test. */
1861 	test_basic();
1862 	/* Test hybrid mode; follow symlink initially, then not. */
1863 	test_symlink_hybrid();
1864 	/* Test logical mode; follow all symlinks. */
1865 	test_symlink_logical();
1866 	/* Test logical mode; prevent loop in symlinks. */
1867 	test_symlink_logical_loop();
1868 	/* Test to restore atime. */
1869 	test_restore_atime();
1870 	/* Test callbacks. */
1871 	test_callbacks();
1872 	/* Test nodump. */
1873 	test_nodump();
1874 	/* Test parent overshoot. */
1875 	test_parent();
1876 }
1877