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 
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 perform 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 	/* Note: this test uses archive_read_next_header()
740 	   instead of archive_read_next_header2() */
741 	assert((a = archive_read_disk_new()) != NULL);
742 	assertEqualIntA(a, ARCHIVE_OK,
743 	    archive_read_disk_set_symlink_logical(a));
744 
745 	/*
746 	 * Specified file is a symbolic link file.
747 	 */
748 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l/ld1"));
749 	file_count = 5;
750 
751 	while (file_count--) {
752 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
753 		if (strcmp(archive_entry_pathname(ae), "l/ld1") == 0) {
754 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
755 		} else if (strcmp(archive_entry_pathname(ae),
756 		    "l/ld1/file1") == 0) {
757 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
758 			assertEqualInt(archive_entry_size(ae), 8);
759 			assertEqualIntA(a, ARCHIVE_OK,
760 			    archive_read_data_block(a, &p, &size, &offset));
761 			assertEqualInt((int)size, 8);
762 			assertEqualInt((int)offset, 0);
763 			assertEqualMem(p, "d1/file1", 8);
764 			assertEqualInt(ARCHIVE_EOF,
765 			    archive_read_data_block(a, &p, &size, &offset));
766 			assertEqualInt((int)size, 0);
767 			assertEqualInt((int)offset, 8);
768 		} else if (strcmp(archive_entry_pathname(ae),
769 		    "l/ld1/file2") == 0) {
770 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
771 			assertEqualInt(archive_entry_size(ae), 8);
772 			assertEqualIntA(a, ARCHIVE_OK,
773 			    archive_read_data_block(a, &p, &size, &offset));
774 			assertEqualInt((int)size, 8);
775 			assertEqualInt((int)offset, 0);
776 			assertEqualMem(p, "d1/file2", 8);
777 			assertEqualInt(ARCHIVE_EOF,
778 			    archive_read_data_block(a, &p, &size, &offset));
779 			assertEqualInt((int)size, 0);
780 			assertEqualInt((int)offset, 8);
781 		} else if (strcmp(archive_entry_pathname(ae),
782 		    "l/ld1/link1") == 0) {
783 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
784 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
785 			assertEqualInt(archive_entry_size(ae), 8);
786 			assertEqualIntA(a, ARCHIVE_OK,
787 			    archive_read_data_block(a, &p, &size, &offset));
788 			assertEqualInt((int)size, 8);
789 			assertEqualInt((int)offset, 0);
790 			assertEqualMem(p, "d1/file1", 8);
791 			assertEqualInt(ARCHIVE_EOF,
792 			    archive_read_data_block(a, &p, &size, &offset));
793 			assertEqualInt((int)size, 0);
794 			assertEqualInt((int)offset, 8);
795 		} else if (strcmp(archive_entry_pathname(ae),
796 		    "l/ld1/linkX") == 0) {
797 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
798 		}
799 		if (archive_entry_filetype(ae) == AE_IFDIR) {
800 			/* Descend into the current object */
801 			assertEqualIntA(a, ARCHIVE_OK,
802 			    archive_read_disk_descend(a));
803 		}
804 	}
805 	/* There is no entry. */
806 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
807 	/* Close the disk object. */
808 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
809 
810 	/*
811 	 * Specified file is a directory and it has symbolic files.
812 	 */
813 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l"));
814 	file_count = 13;
815 
816 	while (file_count--) {
817 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
818 		if (strcmp(archive_entry_pathname(ae), "l") == 0) {
819 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
820 		} else if (strcmp(archive_entry_pathname(ae), "l/d1") == 0) {
821 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
822 		} else if (strcmp(archive_entry_pathname(ae),
823 		    "l/d1/file1") == 0) {
824 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
825 			assertEqualInt(archive_entry_size(ae), 8);
826 			assertEqualIntA(a, ARCHIVE_OK,
827 			    archive_read_data_block(a, &p, &size, &offset));
828 			assertEqualInt((int)size, 8);
829 			assertEqualInt((int)offset, 0);
830 			assertEqualMem(p, "d1/file1", 8);
831 			assertEqualInt(ARCHIVE_EOF,
832 			    archive_read_data_block(a, &p, &size, &offset));
833 			assertEqualInt((int)size, 0);
834 			assertEqualInt((int)offset, 8);
835 		} else if (strcmp(archive_entry_pathname(ae),
836 		    "l/d1/file2") == 0) {
837 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
838 			assertEqualInt(archive_entry_size(ae), 8);
839 			assertEqualIntA(a, ARCHIVE_OK,
840 			    archive_read_data_block(a, &p, &size, &offset));
841 			assertEqualInt((int)size, 8);
842 			assertEqualInt((int)offset, 0);
843 			assertEqualMem(p, "d1/file2", 8);
844 			assertEqualInt(ARCHIVE_EOF,
845 			    archive_read_data_block(a, &p, &size, &offset));
846 			assertEqualInt((int)size, 0);
847 			assertEqualInt((int)offset, 8);
848 		} else if (strcmp(archive_entry_pathname(ae),
849 		    "l/d1/link1") == 0) {
850 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
851 			assertEqualInt(archive_entry_size(ae), 8);
852 			assertEqualIntA(a, ARCHIVE_OK,
853 			    archive_read_data_block(a, &p, &size, &offset));
854 			assertEqualInt((int)size, 8);
855 			assertEqualInt((int)offset, 0);
856 			assertEqualMem(p, "d1/file1", 8);
857 			assertEqualInt(ARCHIVE_EOF,
858 			    archive_read_data_block(a, &p, &size, &offset));
859 			assertEqualInt((int)size, 0);
860 			assertEqualInt((int)offset, 8);
861 		} else if (strcmp(archive_entry_pathname(ae),
862 		    "l/d1/linkX") == 0) {
863 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
864 		} else if (strcmp(archive_entry_pathname(ae), "l/ld1") == 0) {
865 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
866 		} else if (strcmp(archive_entry_pathname(ae),
867 		    "l/ld1/file1") == 0) {
868 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
869 			assertEqualInt(archive_entry_size(ae), 8);
870 			assertEqualIntA(a, ARCHIVE_OK,
871 			    archive_read_data_block(a, &p, &size, &offset));
872 			assertEqualInt((int)size, 8);
873 			assertEqualInt((int)offset, 0);
874 			assertEqualMem(p, "d1/file1", 8);
875 			assertEqualInt(ARCHIVE_EOF,
876 			    archive_read_data_block(a, &p, &size, &offset));
877 			assertEqualInt((int)size, 0);
878 			assertEqualInt((int)offset, 8);
879 		} else if (strcmp(archive_entry_pathname(ae),
880 		    "l/ld1/file2") == 0) {
881 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
882 			assertEqualInt(archive_entry_size(ae), 8);
883 			assertEqualIntA(a, ARCHIVE_OK,
884 			    archive_read_data_block(a, &p, &size, &offset));
885 			assertEqualInt((int)size, 8);
886 			assertEqualInt((int)offset, 0);
887 			assertEqualMem(p, "d1/file2", 8);
888 			assertEqualInt(ARCHIVE_EOF,
889 			    archive_read_data_block(a, &p, &size, &offset));
890 			assertEqualInt((int)size, 0);
891 			assertEqualInt((int)offset, 8);
892 		} else if (strcmp(archive_entry_pathname(ae),
893 		    "l/ld1/link1") == 0) {
894 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
895 			assertEqualInt(archive_entry_size(ae), 8);
896 			assertEqualIntA(a, ARCHIVE_OK,
897 			    archive_read_data_block(a, &p, &size, &offset));
898 			assertEqualInt((int)size, 8);
899 			assertEqualInt((int)offset, 0);
900 			assertEqualMem(p, "d1/file1", 8);
901 			assertEqualInt(ARCHIVE_EOF,
902 			    archive_read_data_block(a, &p, &size, &offset));
903 			assertEqualInt((int)size, 0);
904 			assertEqualInt((int)offset, 8);
905 		} else if (strcmp(archive_entry_pathname(ae),
906 		    "l/ld1/linkX") == 0) {
907 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
908 		} else if (strcmp(archive_entry_pathname(ae),
909 		    "l/link2") == 0) {
910 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
911 			assertEqualInt(archive_entry_size(ae), 8);
912 			assertEqualIntA(a, ARCHIVE_OK,
913 			    archive_read_data_block(a, &p, &size, &offset));
914 			assertEqualInt((int)size, 8);
915 			assertEqualInt((int)offset, 0);
916 			assertEqualMem(p, "d1/file2", 8);
917 			assertEqualInt(ARCHIVE_EOF,
918 			    archive_read_data_block(a, &p, &size, &offset));
919 			assertEqualInt((int)size, 0);
920 			assertEqualInt((int)offset, 8);
921 		} else if (strcmp(archive_entry_pathname(ae),
922 		    "l/linkY") == 0) {
923 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
924 		}
925 		if (archive_entry_filetype(ae) == AE_IFDIR) {
926 			/* Descend into the current object */
927 			assertEqualIntA(a, ARCHIVE_OK,
928 			    archive_read_disk_descend(a));
929 		}
930 	}
931 	/* There is no entry. */
932 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
933 	/* Close the disk object. */
934 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
935 	/* Destroy the disk object. */
936 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
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 	/* On FreeBSD (and likely other systems), atime on
1094 	   dirs does not change when it is read. */
1095 	/* failure("Atime should be restored"); */
1096 	/* assertFileAtimeRecent("at"); */
1097 	failure("Atime should be restored");
1098 	assertFileAtimeRecent("at/f1");
1099 	failure("Atime should be restored");
1100 	assertFileAtimeRecent("at/f2");
1101 	failure("The atime of a empty file should not be changed");
1102 	assertFileAtime("at/fe", 886611, 0);
1103 
1104 	/* Close the disk object. */
1105 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1106 
1107 	/*
1108 	 * Test2: Traversals with archive_read_disk_set_atime_restored().
1109 	 */
1110 	assertUtimes("at/f1", 886600, 0, 886600, 0);
1111 	assertUtimes("at/f2", 886611, 0, 886611, 0);
1112 	assertUtimes("at/fe", 886611, 0, 886611, 0);
1113 	assertUtimes("at", 886622, 0, 886622, 0);
1114 	file_count = 4;
1115 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a));
1116 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1117 
1118 	failure("Directory traversals should work as well");
1119 	while (file_count--) {
1120 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1121 		if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1122 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1123 		} else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1124 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1125 			assertEqualInt(archive_entry_size(ae), 10);
1126 			assertEqualIntA(a, ARCHIVE_OK,
1127 			    archive_read_data_block(a, &p, &size, &offset));
1128 			assertEqualInt((int)size, 10);
1129 			assertEqualInt((int)offset, 0);
1130 			assertEqualMem(p, "0123456789", 10);
1131 			assertEqualInt(ARCHIVE_EOF,
1132 			    archive_read_data_block(a, &p, &size, &offset));
1133 			assertEqualInt((int)size, 0);
1134 			assertEqualInt((int)offset, 10);
1135 		} else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1136 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1137 			assertEqualInt(archive_entry_size(ae), 11);
1138 			assertEqualIntA(a, ARCHIVE_OK,
1139 			    archive_read_data_block(a, &p, &size, &offset));
1140 			assertEqualInt((int)size, 11);
1141 			assertEqualInt((int)offset, 0);
1142 			assertEqualMem(p, "hello world", 11);
1143 			assertEqualInt(ARCHIVE_EOF,
1144 			    archive_read_data_block(a, &p, &size, &offset));
1145 			assertEqualInt((int)size, 0);
1146 			assertEqualInt((int)offset, 11);
1147 		} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1148 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1149 			assertEqualInt(archive_entry_size(ae), 0);
1150 		}
1151 		if (archive_entry_filetype(ae) == AE_IFDIR) {
1152 			/* Descend into the current object */
1153 			assertEqualIntA(a, ARCHIVE_OK,
1154 			    archive_read_disk_descend(a));
1155 		}
1156 	}
1157 	/* There is no entry. */
1158 	failure("There must be no entry");
1159 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1160 
1161 	failure("Atime should be restored");
1162 	assertFileAtime("at", 886622, 0);
1163 	failure("Atime should be restored");
1164 	assertFileAtime("at/f1", 886600, 0);
1165 	failure("Atime should be restored");
1166 	assertFileAtime("at/f2", 886611, 0);
1167 	failure("The atime of a empty file should not be changed");
1168 	assertFileAtime("at/fe", 886611, 0);
1169 
1170 	/* Close the disk object. */
1171 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1172 
1173 	/*
1174 	 * Test3: Traversals with archive_read_disk_set_atime_restored() but
1175 	 * no data read as a listing.
1176 	 */
1177 	assertUtimes("at/f1", 886600, 0, 886600, 0);
1178 	assertUtimes("at/f2", 886611, 0, 886611, 0);
1179 	assertUtimes("at/fe", 886611, 0, 886611, 0);
1180 	assertUtimes("at", 886622, 0, 886622, 0);
1181 	file_count = 4;
1182 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a));
1183 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1184 
1185 	failure("Directory traversals should work as well");
1186 	while (file_count--) {
1187 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1188 		if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1189 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1190 		} else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1191 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1192 			assertEqualInt(archive_entry_size(ae), 10);
1193 		} else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1194 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1195 			assertEqualInt(archive_entry_size(ae), 11);
1196 		} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1197 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1198 			assertEqualInt(archive_entry_size(ae), 0);
1199 		}
1200 		if (archive_entry_filetype(ae) == AE_IFDIR) {
1201 			/* Descend into the current object */
1202 			assertEqualIntA(a, ARCHIVE_OK,
1203 			    archive_read_disk_descend(a));
1204 		}
1205 	}
1206 	/* There is no entry. */
1207 	failure("There must be no entry");
1208 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1209 
1210 	failure("Atime should be restored");
1211 	assertFileAtime("at", 886622, 0);
1212 	failure("Atime should be restored");
1213 	assertFileAtime("at/f1", 886600, 0);
1214 	failure("Atime should be restored");
1215 	assertFileAtime("at/f2", 886611, 0);
1216 	failure("The atime of a empty file should not be changed");
1217 	assertFileAtime("at/fe", 886611, 0);
1218 
1219 	if (!canNodump()) {
1220 		/* Destroy the disk object. */
1221 		assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1222 		archive_entry_free(ae);
1223 		skipping("Can't test atime with nodump on this filesystem");
1224 		return;
1225 	}
1226 
1227 	/* Close the disk object. */
1228 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1229 
1230 	/*
1231 	 * Test4: Traversals with ARCHIVE_READDISK_RESTORE_ATIME and
1232 	 * ARCHIVE_READDISK_HONOR_NODUMP
1233 	 */
1234 	assertSetNodump("at/f1");
1235 	assertSetNodump("at/f2");
1236 	assertUtimes("at/f1", 886600, 0, 886600, 0);
1237 	assertUtimes("at/f2", 886611, 0, 886611, 0);
1238 	assertUtimes("at/fe", 886611, 0, 886611, 0);
1239 	assertUtimes("at", 886622, 0, 886622, 0);
1240 	file_count = 2;
1241 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a,
1242 		ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP));
1243 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1244 
1245 	failure("Directory traversals should work as well");
1246 	while (file_count--) {
1247 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1248 		if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1249 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1250 		} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1251 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1252 			assertEqualInt(archive_entry_size(ae), 0);
1253 		}
1254 		if (archive_entry_filetype(ae) == AE_IFDIR) {
1255 			/* Descend into the current object */
1256 			assertEqualIntA(a, ARCHIVE_OK,
1257 			    archive_read_disk_descend(a));
1258 		}
1259 	}
1260 	/* There is no entry. */
1261 	failure("There must be no entry");
1262 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1263 
1264 	failure("Atime should be restored");
1265 	assertFileAtime("at", 886622, 0);
1266 	failure("Atime should be restored");
1267 	assertFileAtime("at/f1", 886600, 0);
1268 	failure("Atime should be restored");
1269 	assertFileAtime("at/f2", 886611, 0);
1270 	failure("The atime of a empty file should not be changed");
1271 	assertFileAtime("at/fe", 886611, 0);
1272 
1273 	/* Destroy the disk object. */
1274 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1275 	archive_entry_free(ae);
1276 }
1277 
1278 static int
1279 metadata_filter(struct archive *a, void *data, struct archive_entry *ae)
1280 {
1281 	(void)data; /* UNUSED */
1282 
1283 	failure("CTime should be set");
1284 	assertEqualInt(8, archive_entry_ctime_is_set(ae));
1285 	failure("MTime should be set");
1286 	assertEqualInt(16, archive_entry_mtime_is_set(ae));
1287 
1288 	if (archive_entry_mtime(ae) < 886611)
1289 		return (0);
1290 	if (archive_read_disk_can_descend(a)) {
1291 		/* Descend into the current object */
1292 		failure("archive_read_disk_can_descend should work"
1293 			" in metadata filter");
1294 		assertEqualIntA(a, 1, archive_read_disk_can_descend(a));
1295 		failure("archive_read_disk_descend should work"
1296 			" in metadata filter");
1297 		assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a));
1298 	}
1299 	return (1);
1300 }
1301 
1302 static void
1303 test_callbacks(void)
1304 {
1305 	struct archive *a;
1306 	struct archive *m;
1307 	struct archive_entry *ae;
1308 	const void *p;
1309 	size_t size;
1310 	int64_t offset;
1311 	int file_count;
1312 
1313 	assertMakeDir("cb", 0755);
1314 	assertMakeFile("cb/f1", 0644, "0123456789");
1315 	assertMakeFile("cb/f2", 0644, "hello world");
1316 	assertMakeFile("cb/fe", 0644, NULL);
1317 	assertUtimes("cb/f1", 886600, 0, 886600, 0);
1318 	assertUtimes("cb/f2", 886611, 0, 886611, 0);
1319 	assertUtimes("cb/fe", 886611, 0, 886611, 0);
1320 	assertUtimes("cb", 886622, 0, 886622, 0);
1321 
1322 	assert((ae = archive_entry_new()) != NULL);
1323 	assert((a = archive_read_disk_new()) != NULL);
1324 	if (a == NULL) {
1325 		archive_entry_free(ae);
1326 		return;
1327 	}
1328 	assert((m = archive_match_new()) != NULL);
1329 	if (m == NULL) {
1330 		archive_entry_free(ae);
1331 		archive_read_free(a);
1332 		archive_match_free(m);
1333 		return;
1334 	}
1335 
1336 	/*
1337 	 * Test1: Traversals with a name filter.
1338 	 */
1339 	file_count = 3;
1340 	assertEqualIntA(m, ARCHIVE_OK,
1341 	    archive_match_exclude_pattern(m, "cb/f2"));
1342 	assertEqualIntA(a, ARCHIVE_OK,
1343 	    archive_read_disk_set_matching(a, m, NULL, NULL));
1344 	failure("Directory traversals should work as well");
1345 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
1346 	while (file_count--) {
1347 		archive_entry_clear(ae);
1348 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1349 		failure("File 'cb/f2' should be exclueded");
1350 		assert(strcmp(archive_entry_pathname(ae), "cb/f2") != 0);
1351 		if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
1352 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1353 		} else if (strcmp(archive_entry_pathname(ae), "cb/f1") == 0) {
1354 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1355 			assertEqualInt(archive_entry_size(ae), 10);
1356 			assertEqualIntA(a, ARCHIVE_OK,
1357 			    archive_read_data_block(a, &p, &size, &offset));
1358 			assertEqualInt((int)size, 10);
1359 			assertEqualInt((int)offset, 0);
1360 			assertEqualMem(p, "0123456789", 10);
1361 			assertEqualInt(ARCHIVE_EOF,
1362 			    archive_read_data_block(a, &p, &size, &offset));
1363 			assertEqualInt((int)size, 0);
1364 			assertEqualInt((int)offset, 10);
1365 		} else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
1366 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1367 			assertEqualInt(archive_entry_size(ae), 0);
1368 		}
1369 		if (archive_read_disk_can_descend(a)) {
1370 			/* Descend into the current object */
1371 			assertEqualIntA(a, ARCHIVE_OK,
1372 			    archive_read_disk_descend(a));
1373 		}
1374 	}
1375 	/* There is no entry. */
1376 	failure("There should be no entry");
1377 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1378 
1379 	/* Close the disk object. */
1380 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1381 
1382 	/* Reset name filter */
1383 	assertEqualIntA(a, ARCHIVE_OK,
1384 	    archive_read_disk_set_matching(a, NULL, NULL, NULL));
1385 
1386 	/*
1387 	 * Test2: Traversals with a metadata filter.
1388 	 */
1389 	assertUtimes("cb/f1", 886600, 0, 886600, 0);
1390 	assertUtimes("cb/f2", 886611, 0, 886611, 0);
1391 	assertUtimes("cb/fe", 886611, 0, 886611, 0);
1392 	assertUtimes("cb", 886622, 0, 886622, 0);
1393 	file_count = 3;
1394 	assertEqualIntA(a, ARCHIVE_OK,
1395 	    archive_read_disk_set_metadata_filter_callback(a, metadata_filter,
1396 		    NULL));
1397 	failure("Directory traversals should work as well");
1398 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
1399 
1400 	while (file_count--) {
1401 		archive_entry_clear(ae);
1402 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1403 		failure("File 'cb/f1' should be excluded");
1404 		assert(strcmp(archive_entry_pathname(ae), "cb/f1") != 0);
1405 		if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
1406 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1407 		} else if (strcmp(archive_entry_pathname(ae), "cb/f2") == 0) {
1408 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1409 			assertEqualInt(archive_entry_size(ae), 11);
1410 			assertEqualIntA(a, ARCHIVE_OK,
1411 			    archive_read_data_block(a, &p, &size, &offset));
1412 			assertEqualInt((int)size, 11);
1413 			assertEqualInt((int)offset, 0);
1414 			assertEqualMem(p, "hello world", 11);
1415 			assertEqualInt(ARCHIVE_EOF,
1416 			    archive_read_data_block(a, &p, &size, &offset));
1417 			assertEqualInt((int)size, 0);
1418 			assertEqualInt((int)offset, 11);
1419 		} else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
1420 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1421 			assertEqualInt(archive_entry_size(ae), 0);
1422 		}
1423 	}
1424 	/* There is no entry. */
1425 	failure("There should be no entry");
1426 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1427 
1428 	/* Destroy the disk object. */
1429 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1430 	assertEqualInt(ARCHIVE_OK, archive_match_free(m));
1431 	archive_entry_free(ae);
1432 }
1433 
1434 static void
1435 test_nodump(void)
1436 {
1437 	struct archive *a;
1438 	struct archive_entry *ae;
1439 	const void *p;
1440 	size_t size;
1441 	int64_t offset;
1442 	int file_count;
1443 
1444 	if (!canNodump()) {
1445 		skipping("Can't test nodump on this filesystem");
1446 		return;
1447 	}
1448 
1449 	assertMakeDir("nd", 0755);
1450 	assertMakeFile("nd/f1", 0644, "0123456789");
1451 	assertMakeFile("nd/f2", 0644, "hello world");
1452 	assertMakeFile("nd/fe", 0644, NULL);
1453 	assertSetNodump("nd/f2");
1454 	assertUtimes("nd/f1", 886600, 0, 886600, 0);
1455 	assertUtimes("nd/f2", 886611, 0, 886611, 0);
1456 	assertUtimes("nd/fe", 886611, 0, 886611, 0);
1457 	assertUtimes("nd", 886622, 0, 886622, 0);
1458 
1459 	assert((ae = archive_entry_new()) != NULL);
1460 	assert((a = archive_read_disk_new()) != NULL);
1461 
1462 	/*
1463 	 * Test1: Traversals without ARCHIVE_READDISK_HONOR_NODUMP
1464 	 */
1465 	failure("Directory traversals should work as well");
1466 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
1467 
1468 	file_count = 4;
1469 	while (file_count--) {
1470 		archive_entry_clear(ae);
1471 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1472 		if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
1473 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1474 		} else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) {
1475 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1476 			assertEqualInt(archive_entry_size(ae), 10);
1477 			assertEqualIntA(a, ARCHIVE_OK,
1478 			    archive_read_data_block(a, &p, &size, &offset));
1479 			assertEqualInt((int)size, 10);
1480 			assertEqualInt((int)offset, 0);
1481 			assertEqualMem(p, "0123456789", 10);
1482 			assertEqualInt(ARCHIVE_EOF,
1483 			    archive_read_data_block(a, &p, &size, &offset));
1484 			assertEqualInt((int)size, 0);
1485 			assertEqualInt((int)offset, 10);
1486 		} else if (strcmp(archive_entry_pathname(ae), "nd/f2") == 0) {
1487 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1488 			assertEqualInt(archive_entry_size(ae), 11);
1489 			assertEqualIntA(a, ARCHIVE_OK,
1490 			    archive_read_data_block(a, &p, &size, &offset));
1491 			assertEqualInt((int)size, 11);
1492 			assertEqualInt((int)offset, 0);
1493 			assertEqualMem(p, "hello world", 11);
1494 			assertEqualInt(ARCHIVE_EOF,
1495 			    archive_read_data_block(a, &p, &size, &offset));
1496 			assertEqualInt((int)size, 0);
1497 			assertEqualInt((int)offset, 11);
1498 		} else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
1499 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1500 			assertEqualInt(archive_entry_size(ae), 0);
1501 		}
1502 		if (archive_read_disk_can_descend(a)) {
1503 			/* Descend into the current object */
1504 			assertEqualIntA(a, ARCHIVE_OK,
1505 			    archive_read_disk_descend(a));
1506 		}
1507 	}
1508 	/* There is no entry. */
1509 	failure("There should be no entry");
1510 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1511 
1512 	/* Close the disk object. */
1513 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1514 
1515 	/*
1516 	 * Test2: Traversals with ARCHIVE_READDISK_HONOR_NODUMP
1517 	 */
1518 	assertUtimes("nd/f1", 886600, 0, 886600, 0);
1519 	assertUtimes("nd/f2", 886611, 0, 886611, 0);
1520 	assertUtimes("nd/fe", 886611, 0, 886611, 0);
1521 	assertUtimes("nd", 886622, 0, 886622, 0);
1522 
1523 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a,
1524 		ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP));
1525 	failure("Directory traversals should work as well");
1526 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
1527 
1528 	file_count = 3;
1529 	while (file_count--) {
1530 		archive_entry_clear(ae);
1531 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1532 		failure("File 'nd/f2' should be exclueded");
1533 		assert(strcmp(archive_entry_pathname(ae), "nd/f2") != 0);
1534 		if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
1535 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1536 		} else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) {
1537 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1538 			assertEqualInt(archive_entry_size(ae), 10);
1539 			assertEqualIntA(a, ARCHIVE_OK,
1540 			    archive_read_data_block(a, &p, &size, &offset));
1541 			assertEqualInt((int)size, 10);
1542 			assertEqualInt((int)offset, 0);
1543 			assertEqualMem(p, "0123456789", 10);
1544 			assertEqualInt(ARCHIVE_EOF,
1545 			    archive_read_data_block(a, &p, &size, &offset));
1546 			assertEqualInt((int)size, 0);
1547 			assertEqualInt((int)offset, 10);
1548 		} else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
1549 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1550 			assertEqualInt(archive_entry_size(ae), 0);
1551 		}
1552 		if (archive_read_disk_can_descend(a)) {
1553 			/* Descend into the current object */
1554 			assertEqualIntA(a, ARCHIVE_OK,
1555 			    archive_read_disk_descend(a));
1556 		}
1557 	}
1558 	/* There is no entry. */
1559 	failure("There should be no entry");
1560 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1561 
1562 	failure("Atime should be restored");
1563 	assertFileAtime("nd/f2", 886611, 0);
1564 
1565 	/* Destroy the disk object. */
1566 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1567 	archive_entry_free(ae);
1568 }
1569 
1570 DEFINE_TEST(test_read_disk_directory_traversals)
1571 {
1572 	/* Basic test. */
1573 	test_basic();
1574 	/* Test hybrid mode; follow symlink initially, then not. */
1575 	test_symlink_hybrid();
1576 	/* Test logical mode; follow all symlinks. */
1577 	test_symlink_logical();
1578 	/* Test logical mode; prevent loop in symlinks. */
1579 	test_symlink_logical_loop();
1580 	/* Test to restore atime. */
1581 	test_restore_atime();
1582 	/* Test callbacks. */
1583 	test_callbacks();
1584 	/* Test nodump. */
1585 	test_nodump();
1586 }
1587