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 #ifdef PATH_MAX
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 #ifdef PATH_MAX
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 
1051 	if (!atimeIsUpdated()) {
1052 		skipping("Can't test restoring atime on this filesystem");
1053 		return;
1054 	}
1055 
1056 	assertMakeDir("at", 0755);
1057 	assertMakeFile("at/f1", 0644, "0123456789");
1058 	assertMakeFile("at/f2", 0644, "hello world");
1059 	assertMakeFile("at/fe", 0644, NULL);
1060 	assertUtimes("at/f1", 886600, 0, 886600, 0);
1061 	assertUtimes("at/f2", 886611, 0, 886611, 0);
1062 	assertUtimes("at/fe", 886611, 0, 886611, 0);
1063 	assertUtimes("at", 886622, 0, 886622, 0);
1064 	file_count = 4;
1065 
1066 	assert((ae = archive_entry_new()) != NULL);
1067 	assert((a = archive_read_disk_new()) != NULL);
1068 
1069 	/*
1070 	 * Test1: Traversals without archive_read_disk_set_atime_restored().
1071 	 */
1072 	failure("Directory traversals should work as well");
1073 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1074 	while (file_count--) {
1075 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1076 		if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1077 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1078 		} else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1079 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1080 			assertEqualInt(archive_entry_size(ae), 10);
1081 			assertEqualIntA(a, ARCHIVE_OK,
1082 			    archive_read_data_block(a, &p, &size, &offset));
1083 			assertEqualInt((int)size, 10);
1084 			assertEqualInt((int)offset, 0);
1085 			assertEqualMem(p, "0123456789", 10);
1086 			assertEqualInt(ARCHIVE_EOF,
1087 			    archive_read_data_block(a, &p, &size, &offset));
1088 			assertEqualInt((int)size, 0);
1089 			assertEqualInt((int)offset, 10);
1090 		} else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1091 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1092 			assertEqualInt(archive_entry_size(ae), 11);
1093 			assertEqualIntA(a, ARCHIVE_OK,
1094 			    archive_read_data_block(a, &p, &size, &offset));
1095 			assertEqualInt((int)size, 11);
1096 			assertEqualInt((int)offset, 0);
1097 			assertEqualMem(p, "hello world", 11);
1098 			assertEqualInt(ARCHIVE_EOF,
1099 			    archive_read_data_block(a, &p, &size, &offset));
1100 			assertEqualInt((int)size, 0);
1101 			assertEqualInt((int)offset, 11);
1102 		} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1103 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1104 			assertEqualInt(archive_entry_size(ae), 0);
1105 		}
1106 		if (archive_entry_filetype(ae) == AE_IFDIR) {
1107 			/* Descend into the current object */
1108 			assertEqualIntA(a, ARCHIVE_OK,
1109 			    archive_read_disk_descend(a));
1110 		}
1111 	}
1112 	/* There is no entry. */
1113 	failure("There must be no entry");
1114 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1115 
1116 	/* On FreeBSD (and likely other systems), atime on
1117 	   dirs does not change when it is read. */
1118 	/* failure("Atime should be restored"); */
1119 	/* assertFileAtimeRecent("at"); */
1120 	failure("Atime should be restored");
1121 	assertFileAtimeRecent("at/f1");
1122 	failure("Atime should be restored");
1123 	assertFileAtimeRecent("at/f2");
1124 	failure("The atime of a empty file should not be changed");
1125 	assertFileAtime("at/fe", 886611, 0);
1126 
1127 	/* Close the disk object. */
1128 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1129 
1130 	/*
1131 	 * Test2: Traversals with archive_read_disk_set_atime_restored().
1132 	 */
1133 	assertUtimes("at/f1", 886600, 0, 886600, 0);
1134 	assertUtimes("at/f2", 886611, 0, 886611, 0);
1135 	assertUtimes("at/fe", 886611, 0, 886611, 0);
1136 	assertUtimes("at", 886622, 0, 886622, 0);
1137 	file_count = 4;
1138 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a));
1139 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1140 
1141 	failure("Directory traversals should work as well");
1142 	while (file_count--) {
1143 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1144 		if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1145 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1146 		} else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1147 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1148 			assertEqualInt(archive_entry_size(ae), 10);
1149 			assertEqualIntA(a, ARCHIVE_OK,
1150 			    archive_read_data_block(a, &p, &size, &offset));
1151 			assertEqualInt((int)size, 10);
1152 			assertEqualInt((int)offset, 0);
1153 			assertEqualMem(p, "0123456789", 10);
1154 			assertEqualInt(ARCHIVE_EOF,
1155 			    archive_read_data_block(a, &p, &size, &offset));
1156 			assertEqualInt((int)size, 0);
1157 			assertEqualInt((int)offset, 10);
1158 		} else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1159 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1160 			assertEqualInt(archive_entry_size(ae), 11);
1161 			assertEqualIntA(a, ARCHIVE_OK,
1162 			    archive_read_data_block(a, &p, &size, &offset));
1163 			assertEqualInt((int)size, 11);
1164 			assertEqualInt((int)offset, 0);
1165 			assertEqualMem(p, "hello world", 11);
1166 			assertEqualInt(ARCHIVE_EOF,
1167 			    archive_read_data_block(a, &p, &size, &offset));
1168 			assertEqualInt((int)size, 0);
1169 			assertEqualInt((int)offset, 11);
1170 		} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1171 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1172 			assertEqualInt(archive_entry_size(ae), 0);
1173 		}
1174 		if (archive_entry_filetype(ae) == AE_IFDIR) {
1175 			/* Descend into the current object */
1176 			assertEqualIntA(a, ARCHIVE_OK,
1177 			    archive_read_disk_descend(a));
1178 		}
1179 	}
1180 	/* There is no entry. */
1181 	failure("There must be no entry");
1182 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1183 
1184 	failure("Atime should be restored");
1185 	assertFileAtime("at", 886622, 0);
1186 	failure("Atime should be restored");
1187 	assertFileAtime("at/f1", 886600, 0);
1188 	failure("Atime should be restored");
1189 	assertFileAtime("at/f2", 886611, 0);
1190 	failure("The atime of a empty file should not be changed");
1191 	assertFileAtime("at/fe", 886611, 0);
1192 
1193 	/* Close the disk object. */
1194 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1195 
1196 	/*
1197 	 * Test3: Traversals with archive_read_disk_set_atime_restored() but
1198 	 * no data read as a listing.
1199 	 */
1200 	assertUtimes("at/f1", 886600, 0, 886600, 0);
1201 	assertUtimes("at/f2", 886611, 0, 886611, 0);
1202 	assertUtimes("at/fe", 886611, 0, 886611, 0);
1203 	assertUtimes("at", 886622, 0, 886622, 0);
1204 	file_count = 4;
1205 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a));
1206 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1207 
1208 	failure("Directory traversals should work as well");
1209 	while (file_count--) {
1210 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1211 		if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1212 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1213 		} else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1214 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1215 			assertEqualInt(archive_entry_size(ae), 10);
1216 		} else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1217 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1218 			assertEqualInt(archive_entry_size(ae), 11);
1219 		} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1220 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1221 			assertEqualInt(archive_entry_size(ae), 0);
1222 		}
1223 		if (archive_entry_filetype(ae) == AE_IFDIR) {
1224 			/* Descend into the current object */
1225 			assertEqualIntA(a, ARCHIVE_OK,
1226 			    archive_read_disk_descend(a));
1227 		}
1228 	}
1229 	/* There is no entry. */
1230 	failure("There must be no entry");
1231 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1232 
1233 	failure("Atime should be restored");
1234 	assertFileAtime("at", 886622, 0);
1235 	failure("Atime should be restored");
1236 	assertFileAtime("at/f1", 886600, 0);
1237 	failure("Atime should be restored");
1238 	assertFileAtime("at/f2", 886611, 0);
1239 	failure("The atime of a empty file should not be changed");
1240 	assertFileAtime("at/fe", 886611, 0);
1241 
1242 	if (!canNodump()) {
1243 		/* Destroy the disk object. */
1244 		assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1245 		archive_entry_free(ae);
1246 		skipping("Can't test atime with nodump on this filesystem");
1247 		return;
1248 	}
1249 
1250 	/* Close the disk object. */
1251 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1252 
1253 	/*
1254 	 * Test4: Traversals with ARCHIVE_READDISK_RESTORE_ATIME and
1255 	 * ARCHIVE_READDISK_HONOR_NODUMP
1256 	 */
1257 	assertSetNodump("at/f1");
1258 	assertSetNodump("at/f2");
1259 	assertUtimes("at/f1", 886600, 0, 886600, 0);
1260 	assertUtimes("at/f2", 886611, 0, 886611, 0);
1261 	assertUtimes("at/fe", 886611, 0, 886611, 0);
1262 	assertUtimes("at", 886622, 0, 886622, 0);
1263 	file_count = 2;
1264 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a,
1265 		ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP));
1266 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1267 
1268 	failure("Directory traversals should work as well");
1269 	while (file_count--) {
1270 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1271 		if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1272 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1273 		} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1274 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1275 			assertEqualInt(archive_entry_size(ae), 0);
1276 		}
1277 		if (archive_entry_filetype(ae) == AE_IFDIR) {
1278 			/* Descend into the current object */
1279 			assertEqualIntA(a, ARCHIVE_OK,
1280 			    archive_read_disk_descend(a));
1281 		}
1282 	}
1283 	/* There is no entry. */
1284 	failure("There must be no entry");
1285 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1286 
1287 	failure("Atime should be restored");
1288 	assertFileAtime("at", 886622, 0);
1289 	failure("Atime should be restored");
1290 	assertFileAtime("at/f1", 886600, 0);
1291 	failure("Atime should be restored");
1292 	assertFileAtime("at/f2", 886611, 0);
1293 	failure("The atime of a empty file should not be changed");
1294 	assertFileAtime("at/fe", 886611, 0);
1295 
1296 	/* Destroy the disk object. */
1297 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1298 	archive_entry_free(ae);
1299 }
1300 
1301 static int
1302 metadata_filter(struct archive *a, void *data, struct archive_entry *ae)
1303 {
1304 	(void)data; /* UNUSED */
1305 
1306 	failure("CTime should be set");
1307 	assertEqualInt(8, archive_entry_ctime_is_set(ae));
1308 	failure("MTime should be set");
1309 	assertEqualInt(16, archive_entry_mtime_is_set(ae));
1310 
1311 	if (archive_entry_mtime(ae) < 886611)
1312 		return (0);
1313 	if (archive_read_disk_can_descend(a)) {
1314 		/* Descend into the current object */
1315 		failure("archive_read_disk_can_descend should work"
1316 			" in metadata filter");
1317 		assertEqualIntA(a, 1, archive_read_disk_can_descend(a));
1318 		failure("archive_read_disk_descend should work"
1319 			" in metadata filter");
1320 		assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a));
1321 	}
1322 	return (1);
1323 }
1324 
1325 static void
1326 test_callbacks(void)
1327 {
1328 	struct archive *a;
1329 	struct archive *m;
1330 	struct archive_entry *ae;
1331 	const void *p;
1332 	size_t size;
1333 	int64_t offset;
1334 	int file_count;
1335 
1336 	assertMakeDir("cb", 0755);
1337 	assertMakeFile("cb/f1", 0644, "0123456789");
1338 	assertMakeFile("cb/f2", 0644, "hello world");
1339 	assertMakeFile("cb/fe", 0644, NULL);
1340 	assertUtimes("cb/f1", 886600, 0, 886600, 0);
1341 	assertUtimes("cb/f2", 886611, 0, 886611, 0);
1342 	assertUtimes("cb/fe", 886611, 0, 886611, 0);
1343 	assertUtimes("cb", 886622, 0, 886622, 0);
1344 
1345 	assert((ae = archive_entry_new()) != NULL);
1346 	assert((a = archive_read_disk_new()) != NULL);
1347 	if (a == NULL) {
1348 		archive_entry_free(ae);
1349 		return;
1350 	}
1351 	assert((m = archive_match_new()) != NULL);
1352 	if (m == NULL) {
1353 		archive_entry_free(ae);
1354 		archive_read_free(a);
1355 		archive_match_free(m);
1356 		return;
1357 	}
1358 
1359 	/*
1360 	 * Test1: Traversals with a name filter.
1361 	 */
1362 	file_count = 3;
1363 	assertEqualIntA(m, ARCHIVE_OK,
1364 	    archive_match_exclude_pattern(m, "cb/f2"));
1365 	assertEqualIntA(a, ARCHIVE_OK,
1366 	    archive_read_disk_set_matching(a, m, NULL, NULL));
1367 	failure("Directory traversals should work as well");
1368 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
1369 	while (file_count--) {
1370 		archive_entry_clear(ae);
1371 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1372 		failure("File 'cb/f2' should be exclueded");
1373 		assert(strcmp(archive_entry_pathname(ae), "cb/f2") != 0);
1374 		if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
1375 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1376 		} else if (strcmp(archive_entry_pathname(ae), "cb/f1") == 0) {
1377 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1378 			assertEqualInt(archive_entry_size(ae), 10);
1379 			assertEqualIntA(a, ARCHIVE_OK,
1380 			    archive_read_data_block(a, &p, &size, &offset));
1381 			assertEqualInt((int)size, 10);
1382 			assertEqualInt((int)offset, 0);
1383 			assertEqualMem(p, "0123456789", 10);
1384 			assertEqualInt(ARCHIVE_EOF,
1385 			    archive_read_data_block(a, &p, &size, &offset));
1386 			assertEqualInt((int)size, 0);
1387 			assertEqualInt((int)offset, 10);
1388 		} else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
1389 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1390 			assertEqualInt(archive_entry_size(ae), 0);
1391 		}
1392 		if (archive_read_disk_can_descend(a)) {
1393 			/* Descend into the current object */
1394 			assertEqualIntA(a, ARCHIVE_OK,
1395 			    archive_read_disk_descend(a));
1396 		}
1397 	}
1398 	/* There is no entry. */
1399 	failure("There should be no entry");
1400 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1401 
1402 	/* Close the disk object. */
1403 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1404 
1405 	/* Reset name filter */
1406 	assertEqualIntA(a, ARCHIVE_OK,
1407 	    archive_read_disk_set_matching(a, NULL, NULL, NULL));
1408 
1409 	/*
1410 	 * Test2: Traversals with a metadata filter.
1411 	 */
1412 	assertUtimes("cb/f1", 886600, 0, 886600, 0);
1413 	assertUtimes("cb/f2", 886611, 0, 886611, 0);
1414 	assertUtimes("cb/fe", 886611, 0, 886611, 0);
1415 	assertUtimes("cb", 886622, 0, 886622, 0);
1416 	file_count = 3;
1417 	assertEqualIntA(a, ARCHIVE_OK,
1418 	    archive_read_disk_set_metadata_filter_callback(a, metadata_filter,
1419 		    NULL));
1420 	failure("Directory traversals should work as well");
1421 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
1422 
1423 	while (file_count--) {
1424 		archive_entry_clear(ae);
1425 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1426 		failure("File 'cb/f1' should be excluded");
1427 		assert(strcmp(archive_entry_pathname(ae), "cb/f1") != 0);
1428 		if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
1429 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1430 		} else if (strcmp(archive_entry_pathname(ae), "cb/f2") == 0) {
1431 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1432 			assertEqualInt(archive_entry_size(ae), 11);
1433 			assertEqualIntA(a, ARCHIVE_OK,
1434 			    archive_read_data_block(a, &p, &size, &offset));
1435 			assertEqualInt((int)size, 11);
1436 			assertEqualInt((int)offset, 0);
1437 			assertEqualMem(p, "hello world", 11);
1438 			assertEqualInt(ARCHIVE_EOF,
1439 			    archive_read_data_block(a, &p, &size, &offset));
1440 			assertEqualInt((int)size, 0);
1441 			assertEqualInt((int)offset, 11);
1442 		} else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
1443 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1444 			assertEqualInt(archive_entry_size(ae), 0);
1445 		}
1446 	}
1447 	/* There is no entry. */
1448 	failure("There should be no entry");
1449 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1450 
1451 	/* Destroy the disk object. */
1452 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1453 	assertEqualInt(ARCHIVE_OK, archive_match_free(m));
1454 	archive_entry_free(ae);
1455 }
1456 
1457 static void
1458 test_nodump(void)
1459 {
1460 	struct archive *a;
1461 	struct archive_entry *ae;
1462 	const void *p;
1463 	size_t size;
1464 	int64_t offset;
1465 	int file_count;
1466 
1467 	if (!canNodump()) {
1468 		skipping("Can't test nodump on this filesystem");
1469 		return;
1470 	}
1471 
1472 	assertMakeDir("nd", 0755);
1473 	assertMakeFile("nd/f1", 0644, "0123456789");
1474 	assertMakeFile("nd/f2", 0644, "hello world");
1475 	assertMakeFile("nd/fe", 0644, NULL);
1476 	assertSetNodump("nd/f2");
1477 	assertUtimes("nd/f1", 886600, 0, 886600, 0);
1478 	assertUtimes("nd/f2", 886611, 0, 886611, 0);
1479 	assertUtimes("nd/fe", 886611, 0, 886611, 0);
1480 	assertUtimes("nd", 886622, 0, 886622, 0);
1481 
1482 	assert((ae = archive_entry_new()) != NULL);
1483 	assert((a = archive_read_disk_new()) != NULL);
1484 
1485 	/*
1486 	 * Test1: Traversals without ARCHIVE_READDISK_HONOR_NODUMP
1487 	 */
1488 	failure("Directory traversals should work as well");
1489 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
1490 
1491 	file_count = 4;
1492 	while (file_count--) {
1493 		archive_entry_clear(ae);
1494 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1495 		if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
1496 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1497 		} else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) {
1498 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1499 			assertEqualInt(archive_entry_size(ae), 10);
1500 			assertEqualIntA(a, ARCHIVE_OK,
1501 			    archive_read_data_block(a, &p, &size, &offset));
1502 			assertEqualInt((int)size, 10);
1503 			assertEqualInt((int)offset, 0);
1504 			assertEqualMem(p, "0123456789", 10);
1505 			assertEqualInt(ARCHIVE_EOF,
1506 			    archive_read_data_block(a, &p, &size, &offset));
1507 			assertEqualInt((int)size, 0);
1508 			assertEqualInt((int)offset, 10);
1509 		} else if (strcmp(archive_entry_pathname(ae), "nd/f2") == 0) {
1510 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1511 			assertEqualInt(archive_entry_size(ae), 11);
1512 			assertEqualIntA(a, ARCHIVE_OK,
1513 			    archive_read_data_block(a, &p, &size, &offset));
1514 			assertEqualInt((int)size, 11);
1515 			assertEqualInt((int)offset, 0);
1516 			assertEqualMem(p, "hello world", 11);
1517 			assertEqualInt(ARCHIVE_EOF,
1518 			    archive_read_data_block(a, &p, &size, &offset));
1519 			assertEqualInt((int)size, 0);
1520 			assertEqualInt((int)offset, 11);
1521 		} else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
1522 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1523 			assertEqualInt(archive_entry_size(ae), 0);
1524 		}
1525 		if (archive_read_disk_can_descend(a)) {
1526 			/* Descend into the current object */
1527 			assertEqualIntA(a, ARCHIVE_OK,
1528 			    archive_read_disk_descend(a));
1529 		}
1530 	}
1531 	/* There is no entry. */
1532 	failure("There should be no entry");
1533 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1534 
1535 	/* Close the disk object. */
1536 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1537 
1538 	/*
1539 	 * Test2: Traversals with ARCHIVE_READDISK_HONOR_NODUMP
1540 	 */
1541 	assertUtimes("nd/f1", 886600, 0, 886600, 0);
1542 	assertUtimes("nd/f2", 886611, 0, 886611, 0);
1543 	assertUtimes("nd/fe", 886611, 0, 886611, 0);
1544 	assertUtimes("nd", 886622, 0, 886622, 0);
1545 
1546 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a,
1547 		ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP));
1548 	failure("Directory traversals should work as well");
1549 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
1550 
1551 	file_count = 3;
1552 	while (file_count--) {
1553 		archive_entry_clear(ae);
1554 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1555 		failure("File 'nd/f2' should be exclueded");
1556 		assert(strcmp(archive_entry_pathname(ae), "nd/f2") != 0);
1557 		if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
1558 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1559 		} else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) {
1560 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1561 			assertEqualInt(archive_entry_size(ae), 10);
1562 			assertEqualIntA(a, ARCHIVE_OK,
1563 			    archive_read_data_block(a, &p, &size, &offset));
1564 			assertEqualInt((int)size, 10);
1565 			assertEqualInt((int)offset, 0);
1566 			assertEqualMem(p, "0123456789", 10);
1567 			assertEqualInt(ARCHIVE_EOF,
1568 			    archive_read_data_block(a, &p, &size, &offset));
1569 			assertEqualInt((int)size, 0);
1570 			assertEqualInt((int)offset, 10);
1571 		} else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
1572 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1573 			assertEqualInt(archive_entry_size(ae), 0);
1574 		}
1575 		if (archive_read_disk_can_descend(a)) {
1576 			/* Descend into the current object */
1577 			assertEqualIntA(a, ARCHIVE_OK,
1578 			    archive_read_disk_descend(a));
1579 		}
1580 	}
1581 	/* There is no entry. */
1582 	failure("There should be no entry");
1583 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1584 
1585 	failure("Atime should be restored");
1586 	assertFileAtime("nd/f2", 886611, 0);
1587 
1588 	/* Destroy the disk object. */
1589 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1590 	archive_entry_free(ae);
1591 }
1592 
1593 static void
1594 test_parent(void)
1595 {
1596 	struct archive *a;
1597 	struct archive_entry *ae;
1598 	const void *p;
1599 	size_t size;
1600 	int64_t offset;
1601 	int file_count;
1602 	int match_count;
1603 	int r;
1604 
1605 	assertMakeDir("lock", 0311);
1606 	assertMakeDir("lock/dir1", 0755);
1607 	assertMakeFile("lock/dir1/f1", 0644, "0123456789");
1608 	assertMakeDir("lock/lock2", 0311);
1609 	assertMakeDir("lock/lock2/dir1", 0755);
1610 	assertMakeFile("lock/lock2/dir1/f1", 0644, "0123456789");
1611 
1612 	assert((ae = archive_entry_new()) != NULL);
1613 	assert((a = archive_read_disk_new()) != NULL);
1614 
1615 	/*
1616 	 * Test1: Traverse lock/dir1 as .
1617 	 */
1618 	assertChdir("lock/dir1");
1619 
1620 	failure("Directory traversals should work as well");
1621 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "."));
1622 
1623 	file_count = 2;
1624 	match_count = 0;
1625 	while (file_count--) {
1626 		archive_entry_clear(ae);
1627 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1628 		if (strcmp(archive_entry_pathname(ae), ".") == 0) {
1629 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1630 			++match_count;
1631 		} else if (strcmp(archive_entry_pathname(ae), "./f1") == 0) {
1632 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1633 			assertEqualInt(archive_entry_size(ae), 10);
1634 			assertEqualIntA(a, ARCHIVE_OK,
1635 			    archive_read_data_block(a, &p, &size, &offset));
1636 			assertEqualInt((int)size, 10);
1637 			assertEqualInt((int)offset, 0);
1638 			assertEqualMem(p, "0123456789", 10);
1639 			assertEqualInt(ARCHIVE_EOF,
1640 			    archive_read_data_block(a, &p, &size, &offset));
1641 			assertEqualInt((int)size, 0);
1642 			assertEqualInt((int)offset, 10);
1643 			++match_count;
1644 		}
1645 		if (archive_read_disk_can_descend(a)) {
1646 			/* Descend into the current object */
1647 			assertEqualIntA(a, ARCHIVE_OK,
1648 			    archive_read_disk_descend(a));
1649 		}
1650 	}
1651 	failure("Did not match expected filenames");
1652 	assertEqualInt(match_count, 2);
1653 	/*
1654 	 * There is no entry. This will however fail if the directory traverse
1655 	 * tries to ascend past the initial directory, since it lacks permission
1656 	 * to do so.
1657 	 */
1658 	failure("There should be no entry and no error");
1659 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1660 
1661 	/* Close the disk object. */
1662 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1663 
1664 	assertChdir("../..");
1665 
1666 	/*
1667 	 * Test2: Traverse lock/dir1 directly
1668 	 */
1669 	failure("Directory traversals should work as well");
1670 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock/dir1"));
1671 
1672 	file_count = 2;
1673 	match_count = 0;
1674 	while (file_count--) {
1675 		archive_entry_clear(ae);
1676 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1677 		if (strcmp(archive_entry_pathname(ae), "lock/dir1") == 0) {
1678 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1679 			++match_count;
1680 		} else if (strcmp(archive_entry_pathname(ae), "lock/dir1/f1") == 0) {
1681 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1682 			assertEqualInt(archive_entry_size(ae), 10);
1683 			assertEqualIntA(a, ARCHIVE_OK,
1684 			    archive_read_data_block(a, &p, &size, &offset));
1685 			assertEqualInt((int)size, 10);
1686 			assertEqualInt((int)offset, 0);
1687 			assertEqualMem(p, "0123456789", 10);
1688 			assertEqualInt(ARCHIVE_EOF,
1689 			    archive_read_data_block(a, &p, &size, &offset));
1690 			assertEqualInt((int)size, 0);
1691 			assertEqualInt((int)offset, 10);
1692 			++match_count;
1693 		}
1694 		if (archive_read_disk_can_descend(a)) {
1695 			/* Descend into the current object */
1696 			assertEqualIntA(a, ARCHIVE_OK,
1697 			    archive_read_disk_descend(a));
1698 		}
1699 	}
1700 	failure("Did not match expected filenames");
1701 	assertEqualInt(match_count, 2);
1702 	/*
1703 	 * There is no entry. This will however fail if the directory traverse
1704 	 * tries to ascend past the initial directory, since it lacks permission
1705 	 * to do so.
1706 	 */
1707 	failure("There should be no entry and no error");
1708 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1709 
1710 	/* Close the disk object. */
1711 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1712 
1713 	/*
1714 	 * Test3: Traverse lock/dir1/.
1715 	 */
1716 	failure("Directory traversals should work as well");
1717 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock/dir1/."));
1718 
1719 	file_count = 2;
1720 	match_count = 0;
1721 	while (file_count--) {
1722 		archive_entry_clear(ae);
1723 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1724 		if (strcmp(archive_entry_pathname(ae), "lock/dir1/.") == 0) {
1725 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1726 			++match_count;
1727 		} else if (strcmp(archive_entry_pathname(ae), "lock/dir1/./f1") == 0) {
1728 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1729 			assertEqualInt(archive_entry_size(ae), 10);
1730 			assertEqualIntA(a, ARCHIVE_OK,
1731 			    archive_read_data_block(a, &p, &size, &offset));
1732 			assertEqualInt((int)size, 10);
1733 			assertEqualInt((int)offset, 0);
1734 			assertEqualMem(p, "0123456789", 10);
1735 			assertEqualInt(ARCHIVE_EOF,
1736 			    archive_read_data_block(a, &p, &size, &offset));
1737 			assertEqualInt((int)size, 0);
1738 			assertEqualInt((int)offset, 10);
1739 			++match_count;
1740 		}
1741 		if (archive_read_disk_can_descend(a)) {
1742 			/* Descend into the current object */
1743 			assertEqualIntA(a, ARCHIVE_OK,
1744 			    archive_read_disk_descend(a));
1745 		}
1746 	}
1747 	failure("Did not match expected filenames");
1748 	assertEqualInt(match_count, 2);
1749 	/*
1750 	 * There is no entry. This will however fail if the directory traverse
1751 	 * tries to ascend past the initial directory, since it lacks permission
1752 	 * to do so.
1753 	 */
1754 	failure("There should be no entry and no error");
1755 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1756 
1757 	/* Close the disk object. */
1758 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1759 
1760 	/*
1761 	 * Test4: Traverse lock/lock2/dir1 from inside lock.
1762 	 *
1763 	 * This test is expected to fail on platforms with no O_EXEC or
1764 	 * equivalent (e.g. O_PATH on Linux or O_SEARCH on SunOS), because
1765 	 * the current traversal code can't handle the case where it can't
1766 	 * obtain an open fd for the initial current directory. We need to
1767 	 * check that condition here, because if O_EXEC _does_ exist, we don't
1768 	 * want to overlook any failure.
1769 	 */
1770 	assertChdir("lock");
1771 
1772 	failure("Directory traversals should work as well");
1773 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock2/dir1"));
1774 
1775 	archive_entry_clear(ae);
1776 	r = archive_read_next_header2(a, ae);
1777 	if (r == ARCHIVE_FAILED) {
1778 #if defined(O_PATH) || defined(O_SEARCH) || \
1779  (defined(__FreeBSD__) && defined(O_EXEC))
1780 		assertEqualIntA(a, ARCHIVE_OK, r);
1781 #endif
1782 		/* Close the disk object. */
1783 		archive_read_close(a);
1784 	} else {
1785 		file_count = 2;
1786 		match_count = 0;
1787 		while (file_count--) {
1788 			if (file_count == 0)
1789 				assertEqualIntA(a, ARCHIVE_OK,
1790 				    archive_read_next_header2(a, ae));
1791 			if (strcmp(archive_entry_pathname(ae),
1792 				"lock2/dir1") == 0) {
1793 				assertEqualInt(archive_entry_filetype(ae),
1794 				    AE_IFDIR);
1795 				++match_count;
1796 			} else if (strcmp(archive_entry_pathname(ae),
1797 				"lock2/dir1/f1") == 0) {
1798 				assertEqualInt(archive_entry_filetype(ae),
1799 				    AE_IFREG);
1800 				assertEqualInt(archive_entry_size(ae), 10);
1801 				assertEqualIntA(a, ARCHIVE_OK,
1802 				    archive_read_data_block(a, &p, &size,
1803 					&offset));
1804 				assertEqualInt((int)size, 10);
1805 				assertEqualInt((int)offset, 0);
1806 				assertEqualMem(p, "0123456789", 10);
1807 				assertEqualInt(ARCHIVE_EOF,
1808 				    archive_read_data_block(a, &p, &size,
1809 					&offset));
1810 				assertEqualInt((int)size, 0);
1811 				assertEqualInt((int)offset, 10);
1812 				++match_count;
1813 			}
1814 			if (archive_read_disk_can_descend(a)) {
1815 				/* Descend into the current object */
1816 				assertEqualIntA(a, ARCHIVE_OK,
1817 				    archive_read_disk_descend(a));
1818 			}
1819 		}
1820 		failure("Did not match expected filenames");
1821 		assertEqualInt(match_count, 2);
1822 		/*
1823 		 * There is no entry. This will however fail if the directory
1824 		 * traverse tries to ascend past the initial directory, since
1825 		 * it lacks permission to do so.
1826 		 */
1827 		failure("There should be no entry and no error");
1828 		assertEqualIntA(a, ARCHIVE_EOF,
1829 		    archive_read_next_header2(a, ae));
1830 
1831 		/* Close the disk object. */
1832 		assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1833 	}
1834 
1835 	assertChdir("..");
1836 
1837 	/* Destroy the disk object. */
1838 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1839 	archive_entry_free(ae);
1840 }
1841 
1842 DEFINE_TEST(test_read_disk_directory_traversals)
1843 {
1844 	/* Basic test. */
1845 	test_basic();
1846 	/* Test hybrid mode; follow symlink initially, then not. */
1847 	test_symlink_hybrid();
1848 	/* Test logical mode; follow all symlinks. */
1849 	test_symlink_logical();
1850 	/* Test logical mode; prevent loop in symlinks. */
1851 	test_symlink_logical_loop();
1852 	/* Test to restore atime. */
1853 	test_restore_atime();
1854 	/* Test callbacks. */
1855 	test_callbacks();
1856 	/* Test nodump. */
1857 	test_nodump();
1858 	/* Test parent overshoot. */
1859 	test_parent();
1860 }
1861