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